The Introspector class provides a standard way for tools to learn about
the properties, events, and methods supported by a target Java Bean.
For each of those three kinds of information, the Introspector will
separately analyze the bean's class and superclasses looking for
either explicit or implicit information and use that information to
build a BeanInfo object that comprehensively describes the target bean.
For each class "Foo", explicit information may be available if there exists
a corresponding "FooBeanInfo" class that provides a non-null value when
queried for the information. We first look for the BeanInfo class by
taking the full package-qualified name of the target bean class and
appending "BeanInfo" to form a new class name. If this fails, then
we take the final classname component of this name, and look for that
class in each of the packages specified in the BeanInfo package search
path.
Thus for a class such as "sun.xyz.OurButton" we would first look for a
BeanInfo class called "sun.xyz.OurButtonBeanInfo" and if that failed we'd
look in each package in the BeanInfo search path for an OurButtonBeanInfo
class. With the default search path, this would mean looking for
"sun.beans.infos.OurButtonBeanInfo".
If a class provides explicit BeanInfo about itself then we add that to
the BeanInfo information we obtained from analyzing any derived classes,
but we regard the explicit information as being definitive for the current
class and its base classes, and do not proceed any further up the superclass
chain.
If we don't find explicit BeanInfo on a class, we use low-level
reflection to study the methods of the class and apply standard design
patterns to identify property accessors, event sources, or public
methods. We then proceed to analyze the class's superclass and add
in the information from it (and possibly on up the superclass chain).
Because the Introspector caches BeanInfo classes for better performance,
take care if you use it in an application that uses
multiple class loaders.
In general, when you destroy a ClassLoader
that has been used to introspect classes,
you should use the
Introspector.flushCaches
or
Introspector.flushFromCaches method
to flush all of the introspected classes out of the cache.
For more information about introspection and design patterns, please
consult the
JavaBeans specification.
Introspect on a Java Bean and learn about all its properties, exposed
methods, and events.
If the BeanInfo class for a Java Bean has been previously Introspected
then the BeanInfo class is retrieved from the BeanInfo cache.
Introspect on a Java bean and learn about all its properties, exposed
methods, and events, subject to some control flags.
If the BeanInfo class for a Java Bean has been previously Introspected
based on the same arguments then the BeanInfo class is retrieved
from the BeanInfo cache.
- Parameters:
beanClass The bean class to be analyzed.flags Flags to control the introspection.
If flags == USE_ALL_BEANINFO then we use all of the BeanInfo
classes we can discover.
If flags == IGNORE_IMMEDIATE_BEANINFO then we ignore any
BeanInfo associated with the specified beanClass.
If flags == IGNORE_ALL_BEANINFO then we ignore all BeanInfo
associated with the specified beanClass or any of its
parent classes.- Returns:
- A BeanInfo object describing the target bean.
- Throws:
IntrospectionException if an exception occurs during
introspection.
Introspect on a Java bean and learn all about its properties, exposed
methods, below a given "stop" point.
If the BeanInfo class for a Java Bean has been previously Introspected
based on the same arguments, then the BeanInfo class is retrieved
from the BeanInfo cache.
- Parameters:
beanClass The bean class to be analyzed.stopClass The baseclass at which to stop the analysis. Any
methods/properties/events in the stopClass or in its baseclasses
will be ignored in the analysis.- Throws:
IntrospectionException if an exception occurs during
introspection.
Only called from the public getBeanInfo methods. This method caches
the Introspected BeanInfo based on the arguments.
Utility method to take a string and convert it to normal Java variable
name capitalization. This normally means converting the first
character from upper case to lower case, but in the (unusual) special
case when there is more than one character and both the first and
second characters are upper case, we leave it alone.
Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
as "URL".
- Parameters:
name The string to be decapitalized.- Returns:
- The decapitalized version of the string.
if (name == null || name.length() == 0) { Gets the list of package names that will be used for
finding BeanInfo classes.
- Returns:
- The array of package names that will be searched in
order to find BeanInfo classes. The default value
for this array is implementation-dependent; e.g.
Sun implementation initially sets to {"sun.beans.infos"}.
Change the list of package names that will be used for
finding BeanInfo classes. The behaviour of
this method is undefined if parameter path
is null.
First, if there is a security manager, its checkPropertiesAccess
method is called. This could result in a SecurityException.
Flush all of the Introspector's internal caches. This method is
not normally required. It is normally only needed by advanced
tools that update existing "Class" objects in-place and need
to make the Introspector re-analyze existing Class objects.
Flush the Introspector's internal cached information for a given class.
This method is not normally required. It is normally only needed
by advanced tools that update existing "Class" objects in-place
and need to make the Introspector re-analyze an existing Class object.
Note that only the direct state associated with the target Class
object is flushed. We do not flush state for other Class objects
with the same name, nor do we flush state for any related Class
objects (such as subclasses), even though their state may include
information indirectly obtained from the target Class object.
if (superClass != stopClass) { Constructs a GenericBeanInfo class from the state of the Introspector
Looks for an explicit BeanInfo class that corresponds to the Class.
First it looks in the existing package that the Class is defined in,
then it checks to see if the class is its own BeanInfo. Finally,
the BeanInfo search path is prepended to the class and searched.
- Returns:
- Instance of an explicit BeanInfo class or null if one isn't found.
for (int j = 0; j < pds.length; j++) { for (int j = 0; j < mds.length; j++) { - Returns:
- An array of PropertyDescriptors describing the editable
properties supported by the target bean.
if (explicitProperties != null) { for (int i = 0; i < methodList.length; i++) { Method method = methodList[i];
int argCount = argTypes.length;
} else if (argCount == 1) { } else if (argCount == 2) { for (int i = 0; i < result.length; i++) { Adds the property descriptor to the list store.
if (descriptors != null) { if ((0 <= index) && (index < descriptors.length)) { Populates the property descriptor table by merging the
lists of Property descriptors.
pd = null; gpd = null; spd = null;
ipd = null; igpd = null; ispd = null;
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) { if (igpd != null && ispd != null) { } else if (gpd != null && spd != null) { } else if (ispd != null) { } else if (igpd != null) { } else if (spd != null) { } else if (gpd != null) { if ( (pd == null) && (list.size() > 0) ) { Adds the property descriptor to the indexedproperty descriptor only if the
types are the same.
The most specific property descriptor will take precedence.
if (read == null && write != null) { if (write == null && read != null) { - Returns:
- An array of EventSetDescriptors describing the kinds of
events fired by the target bean.
if (ix >= 0 && ix < explicitEvents.length) { for (int i = 0 ; i < supers.length; i++) { if (ix >= 0 && ix < supers.length) { if (additional != null) { for (int j = 0 ; j < additional.length; j++) { if (explicitEvents != null) { for (int i = 0 ; i < explicitEvents.length; i++) { for (int i = 0; i < methodList.length; i++) { Method method = methodList[i];
if (listenerName.length() > 0 &&
adds.put(listenerName, method);
if (listenerName.length() > 0 &&
removes.put(listenerName, method);
if (listenerName.length() > 0 &&
gets.put(listenerName, method);
if (adds != null && removes != null) { if (removes.get(listenerName) == null || !listenerName.endsWith("Listener")) { for (int i = 0; i < allMethods.length; i++) { if (allMethods[i] == null) { validMethods.add(allMethods[i]);
for (int i = 0; i < result.length; i++) { - Returns:
- An array of MethodDescriptors describing the private
methods supported by the target bean.
for (int i = 0 ; i < supers.length; i++) { if (additional != null) { for (int j = 0 ; j < additional.length; j++) { if (explicitMethods != null) { for (int i = 0 ; i < explicitMethods.length; i++) { for (int i = 0; i < methodList.length; i++) { Method method = methodList[i];
if (p1.length == p2.length) { for (int i = 0; i < p1.length; i++) { Creates a key for a method in a method cache.
for (int i = 0; i < params.length; i++) { if (argTypes.length != 1) { for (int i = 0; i < result.length; i++) { Internal support for finding a target methodName with a given
parameter list on a given class.
int argCount, Class args[]) { for (int i = 0; i < methods.length; i++) { params.length == argCount) { boolean different = false;
for (int j = 0; j < argCount; j++) { if (params[j] != args[j]) { for (int i = 0 ; i < ifcs.length; i++) { Find a target methodName on a given class.
return findMethod(cls, methodName, argCount, null);
Find a target methodName with specific parameter list on a given class.
Used in the contructors of the EventSetDescriptor,
PropertyDescriptor and the IndexedPropertyDescriptor.
- Parameters:
cls The Class object on which to retrieve the method.methodName Name of the method.argCount Number of arguments for the desired method.args Array of argument types for the method.- Returns:
- the method or null if not found
if (methodName == null) { Return true if class a is either equivalent to class b, or
if class a is a subclass of class b, i.e. if a either "extends"
or "implements" b.
Note tht either or both "Class" objects may represent interfaces.
if (a == null || b == null) { for (int i = 0; i < interfaces.length; i++) { Return true iff the given method throws the given exception.
for (int i = 0; i < exs.length; i++) { if (exs[i] == exception) { Try to create an instance of a named class.
First try the classloader of "sibling", then try the system
classloader then the class loader of the current Thread.
Package private implementation support class for Introspector's
internal use.
Mostly this is used as a placeholder for the descriptors.
Package-private dup constructor
This must isolate the new object from any changes to the old object.
if (old.events != null) { int len = old.events.length;
for (int i = 0; i < len; i++) { if (old.properties != null) { int len = old.properties.length;
for (int i = 0; i < len; i++) { if (old.methods != null) { int len = old.methods.length;
for (int i = 0; i < len; i++) {