Introspector.java revision 4373
146N/A * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. 146N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 146N/A * This code is free software; you can redistribute it and/or modify it 146N/A * under the terms of the GNU General Public License version 2 only, as 146N/A * published by the Free Software Foundation. Oracle designates this 146N/A * particular file as subject to the "Classpath" exception as provided 146N/A * by Oracle in the LICENSE file that accompanied this code. 146N/A * This code is distributed in the hope that it will be useful, but WITHOUT 146N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 146N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 146N/A * version 2 for more details (a copy is included in the LICENSE file that 146N/A * accompanied this code). 146N/A * You should have received a copy of the GNU General Public License version 146N/A * 2 along with this work; if not, write to the Free Software Foundation, 146N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 146N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 146N/A * or visit www.oracle.com if you need additional information or have any 4561N/A * The Introspector class provides a standard way for tools to learn about 4561N/A * the properties, events, and methods supported by a target Java Bean. 3996N/A * For each of those three kinds of information, the Introspector will 3996N/A * separately analyze the bean's class and superclasses looking for 146N/A * either explicit or implicit information and use that information to 146N/A * build a BeanInfo object that comprehensively describes the target bean. 146N/A * For each class "Foo", explicit information may be available if there exists 4236N/A * a corresponding "FooBeanInfo" class that provides a non-null value when 3984N/A * queried for the information. We first look for the BeanInfo class by 3984N/A * taking the full package-qualified name of the target bean class and 3984N/A * appending "BeanInfo" to form a new class name. If this fails, then 146N/A * we take the final classname component of this name, and look for that 206N/A * class in each of the packages specified in the BeanInfo package search 1439N/A * Thus for a class such as "sun.xyz.OurButton" we would first look for a 146N/A * BeanInfo class called "sun.xyz.OurButtonBeanInfo" and if that failed we'd 4236N/A * look in each package in the BeanInfo search path for an OurButtonBeanInfo 1439N/A * class. With the default search path, this would mean looking for 146N/A * "sun.beans.infos.OurButtonBeanInfo". 146N/A * If a class provides explicit BeanInfo about itself then we add that to 146N/A * the BeanInfo information we obtained from analyzing any derived classes, 146N/A * but we regard the explicit information as being definitive for the current 146N/A * class and its base classes, and do not proceed any further up the superclass 146N/A * If we don't find explicit BeanInfo on a class, we use low-level 1439N/A * reflection to study the methods of the class and apply standard design 1439N/A * patterns to identify property accessors, event sources, or public 4236N/A * methods. We then proceed to analyze the class's superclass and add 1439N/A * in the information from it (and possibly on up the superclass chain). 1439N/A * For more information about introspection and design patterns, please 146N/A // Flags that can be used to control getBeanInfo: 4236N/A // Static Caches to speed up introspection. // These should be removed. // Methods maps from Method objects to MethodDescriptors // properties maps from String names to PropertyDescriptors // events maps from String names to EventSetDescriptors //====================================================================== //====================================================================== * Introspect on a Java Bean and learn about all its properties, exposed * If the BeanInfo class for a Java Bean has been previously Introspected * then the BeanInfo class is retrieved from the BeanInfo cache. * @param beanClass The bean class to be analyzed. * @return A BeanInfo object describing the target bean. * @exception IntrospectionException if an exception occurs during * 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. * @param beanClass The bean class to be analyzed. * @param 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 * @return A BeanInfo object describing the target bean. * @exception IntrospectionException if an exception occurs during * 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. * @param beanClass The bean class to be analyzed. * @param stopClass The baseclass at which to stop the analysis. Any * will be ignored in the analysis. * @exception IntrospectionException if an exception occurs during * Introspect on a Java Bean and learn about all its properties, * exposed methods and events, below a given {@code stopClass} point * subject to some control {@code flags}. * <dt>USE_ALL_BEANINFO</dt> * <dd>Any BeanInfo that can be discovered will be used.</dd> * <dt>IGNORE_IMMEDIATE_BEANINFO</dt> * <dd>Any BeanInfo associated with the specified {@code beanClass} will be ignored.</dd> * <dt>IGNORE_ALL_BEANINFO</dt> * <dd>Any BeanInfo associated with the specified {@code beanClass} * or any of its parent classes will be ignored.</dd> * or in its parent classes will be ignored in the analysis. * 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. * @param beanClass the bean class to be analyzed * @param stopClass the parent class at which to stop the analysis * @param flags flags to control the introspection * @return a BeanInfo object describing the target bean * @exception IntrospectionException if an exception occurs during introspection // Same parameters to take advantage of caching. // Old behaviour: Make an independent copy of the BeanInfo. //return new GenericBeanInfo(bi); * 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 * @param name The string to be decapitalized. * @return The decapitalized version of the string. * Gets the list of package names that will be used for * finding BeanInfo classes. * @return 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 * <p>First, if there is a security manager, its <code>checkPropertiesAccess</code> * method is called. This could result in a SecurityException. * @param path Array of package names. * @exception SecurityException if a security manager exists and its * <code>checkPropertiesAccess</code> method doesn't allow setting * @see SecurityManager#checkPropertiesAccess * 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. * @param clz Class object to be flushed. * @throws NullPointerException If the Class object is null. //====================================================================== // Private implementation methods //====================================================================== // Check stopClass is a superClass of startClass. * Constructs a GenericBeanInfo class from the state of the Introspector // the evaluation order here is import, as we evaluate the // event sets and locate PropertyChangeListeners before we * 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. * @param beanClass the class type of the bean * @return Instance of an explicit BeanInfo class or null if one isn't found. * @return An array of PropertyDescriptors describing the editable * properties supported by the target bean. // Check if the bean has its own BeanInfo that will provide // We have no explicit BeanInfo properties. Check with our parent. // Add the explicit BeanInfo data to our results. // Apply some reflection to the current class. // First get an array of all the public methods at this level // Now analyze each method. // Optimization. Don't bother with invalid propertyNames. // This happens if a PropertyDescriptor or IndexedPropertyDescriptor // constructor fins that the method violates details of the deisgn // pattern, e.g. by having an empty name, or a getter returning // If this class or one of its base classes is a PropertyChange // source, then we assume that any properties we discover are "bound". // Allocate and populate the result array. // Set the default index. * Adds the property descriptor to the list store. // replace existing property descriptor // only if we have types to resolve // in the context of this.beanClass * Populates the property descriptor table by merging the * lists of Property descriptors. // First pass. Find the latest getter method. Merge properties // of previous getter methods. // Don't replace the existing read // method if it starts with "is" // Second pass. Find the latest setter method which // has the same type as the getter method. // At this stage we should have either PDs or IPDs for the // representative getters and setters. The order at which the // property descriptors are determined represent the // precedence of the property ordering. // Complete indexed properties set // Merge any classic property descriptors // Complete simple properties set // Merge any classic property descriptors // Merge any classic property descriptors // Very special case to ensure that an IndexedPropertyDescriptor // doesn't contain less information than the enclosed // PropertyDescriptor. If it does, then recreate as a // PropertyDescriptor. See 4168833 // Find the first property descriptor // which does not have getter and setter methods. // See regression bug 4984912. * Adds the property descriptor to the indexedproperty descriptor only if the * The most specific property descriptor will take precedence. // Cannot merge the pd because of type mismatch // Return the most specific pd // Try to add methods which may have been lost in the type change // no consequences for failure. // no consequences for failure. // Handle regular pd merge // Handle regular ipd merge * @return An array of EventSetDescriptors describing the kinds of * events fired by the target bean. // Check if the bean has its own BeanInfo that will provide // We have no explicit BeanInfo events. Check with our parent. // Add the explicit explicitBeanInfo data to our results. // Apply some reflection to the current class. // Get an array of all the public beans methods at this level // Find all suitable "add", "remove" and "get" Listener methods // The name of the listener type is the key for these hashtables // Optimization avoid getParameterTypes // Now look for matching addFooListener+removeFooListener pairs. // Bonus if there is a matching getFooListeners method as well. // Skip any "add" which doesn't have a matching "remove" or // a listener name that doesn't end with Listener // generate a list of Method objects for each of the target methods: // If the adder method throws the TooManyListenersException then it // is a Unicast event source. }
// if (adds != null ... // Allocate and populate the result array. // Set the default index. * @return An array of MethodDescriptors describing the private * methods supported by the target bean. // Check if the bean has its own BeanInfo that will provide // We have no explicit BeanInfo methods. Check with our parent. // Add the explicit explicitBeanInfo data to our results. // Apply some reflection to the current class. // First get an array of all the beans methods at this level // Now analyze each method. // Allocate and populate the result array. // We have to be careful here to distinguish method by both name // This method gets called a *lot, so we try to be efficient. // This is the common case. // We have a collision on method names. This is rare. // Check if old and md have the same type. // We have a collision on method names with different type signatures. * Creates a key for a method in a method cache. // Use explicit info, if available, // OK, fabricate a default BeanDescriptor. // Each customizer should inherit java.awt.Component and implement java.beans.Customizer // according to the section 9.3 of JavaBeans™ specification // We assume that a method is an event handler if it has a single // argument, whose type inherit from java.util.Event. * Internal method to return *public* methods within a class. // Looking up Class.getDeclaredMethods is relatively expensive, // so we cache the results. //====================================================================== // Package private support methods. //====================================================================== * Internal support for finding a target methodName with a given * parameter list on a given class. // For overriden methods we need to find the most derived version. // So we start with the given class and walk up the superclass chain. // make sure method signature matches. // Now check any inherited interfaces. This is necessary both when // the argument class is itself an interface, and when the argument // class is an abstract class. // Note: The original implementation had both methods calling // the 3 arg method. This is preserved but perhaps it should // pass the args array instead of null. * Find a target methodName on a given class. * Find a target methodName with specific parameter list on a given class. * Used in the contructors of the EventSetDescriptor, * PropertyDescriptor and the IndexedPropertyDescriptor. * @param cls The Class object on which to retrieve the method. * @param methodName Name of the method. * @param argCount Number of arguments for the desired method. * @param args Array of argument types for the method. * @return the method or null if not found * 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" * Note tht either or both "Class" objects may represent interfaces. // We rely on the fact that for any given java class or // primtitive type there is a unqiue Class object, so // we can use object equivalence in the comparisons. * Return true iff the given method throws the given 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. // First check with sibling's classloader (if any). }
// end class Introspector//=========================================================================== * Package private implementation support class for Introspector's * 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. for (
int i =
0; i <
len; i++) {
for (
int i =
0; i <
len; i++) {
for (
int i =
0; i <
len; i++) {