95 public final static int IGNORE_ALL_BEANINFO = 3; |
95 public final static int IGNORE_ALL_BEANINFO = 3; |
96 |
96 |
97 // Static Caches to speed up introspection. |
97 // Static Caches to speed up introspection. |
98 private static final WeakCache<Class<?>, Method[]> declaredMethodCache = new WeakCache<>(); |
98 private static final WeakCache<Class<?>, Method[]> declaredMethodCache = new WeakCache<>(); |
99 |
99 |
100 private Class beanClass; |
100 private Class<?> beanClass; |
101 private BeanInfo explicitBeanInfo; |
101 private BeanInfo explicitBeanInfo; |
102 private BeanInfo superBeanInfo; |
102 private BeanInfo superBeanInfo; |
103 private BeanInfo additionalBeanInfo[]; |
103 private BeanInfo additionalBeanInfo[]; |
104 |
104 |
105 private boolean propertyChangeSource = false; |
105 private boolean propertyChangeSource = false; |
106 private static Class eventListenerType = EventListener.class; |
106 private static Class<EventListener> eventListenerType = EventListener.class; |
107 |
107 |
108 // These should be removed. |
108 // These should be removed. |
109 private String defaultEventName; |
109 private String defaultEventName; |
110 private String defaultPropertyName; |
110 private String defaultPropertyName; |
111 private int defaultEventIndex = -1; |
111 private int defaultEventIndex = -1; |
112 private int defaultPropertyIndex = -1; |
112 private int defaultPropertyIndex = -1; |
113 |
113 |
114 // Methods maps from Method objects to MethodDescriptors |
114 // Methods maps from Method names to MethodDescriptors |
115 private Map methods; |
115 private Map<String, MethodDescriptor> methods; |
116 |
116 |
117 // properties maps from String names to PropertyDescriptors |
117 // properties maps from String names to PropertyDescriptors |
118 private Map properties; |
118 private Map<String, PropertyDescriptor> properties; |
119 |
119 |
120 // events maps from String names to EventSetDescriptors |
120 // events maps from String names to EventSetDescriptors |
121 private Map events; |
121 private Map<String, EventSetDescriptor> events; |
122 |
122 |
123 private final static EventSetDescriptor[] EMPTY_EVENTSETDESCRIPTORS = new EventSetDescriptor[0]; |
123 private final static EventSetDescriptor[] EMPTY_EVENTSETDESCRIPTORS = new EventSetDescriptor[0]; |
124 |
124 |
125 static final String ADD_PREFIX = "add"; |
125 static final String ADD_PREFIX = "add"; |
126 static final String REMOVE_PREFIX = "remove"; |
126 static final String REMOVE_PREFIX = "remove"; |
362 |
362 |
363 //====================================================================== |
363 //====================================================================== |
364 // Private implementation methods |
364 // Private implementation methods |
365 //====================================================================== |
365 //====================================================================== |
366 |
366 |
367 private Introspector(Class beanClass, Class stopClass, int flags) |
367 private Introspector(Class<?> beanClass, Class<?> stopClass, int flags) |
368 throws IntrospectionException { |
368 throws IntrospectionException { |
369 this.beanClass = beanClass; |
369 this.beanClass = beanClass; |
370 |
370 |
371 // Check stopClass is a superClass of startClass. |
371 // Check stopClass is a superClass of startClass. |
372 if (stopClass != null) { |
372 if (stopClass != null) { |
373 boolean isSuper = false; |
373 boolean isSuper = false; |
374 for (Class c = beanClass.getSuperclass(); c != null; c = c.getSuperclass()) { |
374 for (Class<?> c = beanClass.getSuperclass(); c != null; c = c.getSuperclass()) { |
375 if (c == stopClass) { |
375 if (c == stopClass) { |
376 isSuper = true; |
376 isSuper = true; |
377 } |
377 } |
378 } |
378 } |
379 if (!isSuper) { |
379 if (!isSuper) { |
384 |
384 |
385 if (flags == USE_ALL_BEANINFO) { |
385 if (flags == USE_ALL_BEANINFO) { |
386 explicitBeanInfo = findExplicitBeanInfo(beanClass); |
386 explicitBeanInfo = findExplicitBeanInfo(beanClass); |
387 } |
387 } |
388 |
388 |
389 Class superClass = beanClass.getSuperclass(); |
389 Class<?> superClass = beanClass.getSuperclass(); |
390 if (superClass != stopClass) { |
390 if (superClass != stopClass) { |
391 int newFlags = flags; |
391 int newFlags = flags; |
392 if (newFlags == IGNORE_IMMEDIATE_BEANINFO) { |
392 if (newFlags == IGNORE_IMMEDIATE_BEANINFO) { |
393 newFlags = USE_ALL_BEANINFO; |
393 newFlags = USE_ALL_BEANINFO; |
394 } |
394 } |
430 * the BeanInfo search path is prepended to the class and searched. |
430 * the BeanInfo search path is prepended to the class and searched. |
431 * |
431 * |
432 * @param beanClass the class type of the bean |
432 * @param beanClass the class type of the bean |
433 * @return Instance of an explicit BeanInfo class or null if one isn't found. |
433 * @return Instance of an explicit BeanInfo class or null if one isn't found. |
434 */ |
434 */ |
435 private static BeanInfo findExplicitBeanInfo(Class beanClass) { |
435 private static BeanInfo findExplicitBeanInfo(Class<?> beanClass) { |
436 return ThreadGroupContext.getContext().getBeanInfoFinder().find(beanClass); |
436 return ThreadGroupContext.getContext().getBeanInfoFinder().find(beanClass); |
437 } |
437 } |
438 |
438 |
439 /** |
439 /** |
440 * @return An array of PropertyDescriptors describing the editable |
440 * @return An array of PropertyDescriptors describing the editable |
480 int mods = method.getModifiers(); |
480 int mods = method.getModifiers(); |
481 if (Modifier.isStatic(mods)) { |
481 if (Modifier.isStatic(mods)) { |
482 continue; |
482 continue; |
483 } |
483 } |
484 String name = method.getName(); |
484 String name = method.getName(); |
485 Class argTypes[] = method.getParameterTypes(); |
485 Class<?>[] argTypes = method.getParameterTypes(); |
486 Class resultType = method.getReturnType(); |
486 Class<?> resultType = method.getReturnType(); |
487 int argCount = argTypes.length; |
487 int argCount = argTypes.length; |
488 PropertyDescriptor pd = null; |
488 PropertyDescriptor pd = null; |
489 |
489 |
490 if (name.length() <= 3 && !name.startsWith(IS_PREFIX)) { |
490 if (name.length() <= 3 && !name.startsWith(IS_PREFIX)) { |
491 // Optimization. Don't bother with invalid propertyNames. |
491 // Optimization. Don't bother with invalid propertyNames. |
539 } |
539 } |
540 } |
540 } |
541 processPropertyDescriptors(); |
541 processPropertyDescriptors(); |
542 |
542 |
543 // Allocate and populate the result array. |
543 // Allocate and populate the result array. |
544 PropertyDescriptor result[] = new PropertyDescriptor[properties.size()]; |
544 PropertyDescriptor result[] = |
545 result = (PropertyDescriptor[])properties.values().toArray(result); |
545 properties.values().toArray(new PropertyDescriptor[properties.size()]); |
546 |
546 |
547 // Set the default index. |
547 // Set the default index. |
548 if (defaultPropertyName != null) { |
548 if (defaultPropertyName != null) { |
549 for (int i = 0; i < result.length; i++) { |
549 for (int i = 0; i < result.length; i++) { |
550 if (defaultPropertyName.equals(result[i].getName())) { |
550 if (defaultPropertyName.equals(result[i].getName())) { |
554 } |
554 } |
555 |
555 |
556 return result; |
556 return result; |
557 } |
557 } |
558 |
558 |
559 private HashMap pdStore = new HashMap(); |
559 private HashMap<String, List<PropertyDescriptor>> pdStore = new HashMap<>(); |
560 |
560 |
561 /** |
561 /** |
562 * Adds the property descriptor to the list store. |
562 * Adds the property descriptor to the list store. |
563 */ |
563 */ |
564 private void addPropertyDescriptor(PropertyDescriptor pd) { |
564 private void addPropertyDescriptor(PropertyDescriptor pd) { |
565 String propName = pd.getName(); |
565 String propName = pd.getName(); |
566 List list = (List)pdStore.get(propName); |
566 List<PropertyDescriptor> list = pdStore.get(propName); |
567 if (list == null) { |
567 if (list == null) { |
568 list = new ArrayList(); |
568 list = new ArrayList<>(); |
569 pdStore.put(propName, list); |
569 pdStore.put(propName, list); |
570 } |
570 } |
571 if (this.beanClass != pd.getClass0()) { |
571 if (this.beanClass != pd.getClass0()) { |
572 // replace existing property descriptor |
572 // replace existing property descriptor |
573 // only if we have types to resolve |
573 // only if we have types to resolve |
618 * Populates the property descriptor table by merging the |
618 * Populates the property descriptor table by merging the |
619 * lists of Property descriptors. |
619 * lists of Property descriptors. |
620 */ |
620 */ |
621 private void processPropertyDescriptors() { |
621 private void processPropertyDescriptors() { |
622 if (properties == null) { |
622 if (properties == null) { |
623 properties = new TreeMap(); |
623 properties = new TreeMap<>(); |
624 } |
624 } |
625 |
625 |
626 List list; |
626 List<PropertyDescriptor> list; |
627 |
627 |
628 PropertyDescriptor pd, gpd, spd; |
628 PropertyDescriptor pd, gpd, spd; |
629 IndexedPropertyDescriptor ipd, igpd, ispd; |
629 IndexedPropertyDescriptor ipd, igpd, ispd; |
630 |
630 |
631 Iterator it = pdStore.values().iterator(); |
631 Iterator<List<PropertyDescriptor>> it = pdStore.values().iterator(); |
632 while (it.hasNext()) { |
632 while (it.hasNext()) { |
633 pd = null; gpd = null; spd = null; |
633 pd = null; gpd = null; spd = null; |
634 ipd = null; igpd = null; ispd = null; |
634 ipd = null; igpd = null; ispd = null; |
635 |
635 |
636 list = (List)it.next(); |
636 list = it.next(); |
637 |
637 |
638 // First pass. Find the latest getter method. Merge properties |
638 // First pass. Find the latest getter method. Merge properties |
639 // of previous getter methods. |
639 // of previous getter methods. |
640 for (int i = 0; i < list.size(); i++) { |
640 for (int i = 0; i < list.size(); i++) { |
641 pd = (PropertyDescriptor)list.get(i); |
641 pd = list.get(i); |
642 if (pd instanceof IndexedPropertyDescriptor) { |
642 if (pd instanceof IndexedPropertyDescriptor) { |
643 ipd = (IndexedPropertyDescriptor)pd; |
643 ipd = (IndexedPropertyDescriptor)pd; |
644 if (ipd.getIndexedReadMethod() != null) { |
644 if (ipd.getIndexedReadMethod() != null) { |
645 if (igpd != null) { |
645 if (igpd != null) { |
646 igpd = new IndexedPropertyDescriptor(igpd, ipd); |
646 igpd = new IndexedPropertyDescriptor(igpd, ipd); |
665 } |
665 } |
666 |
666 |
667 // Second pass. Find the latest setter method which |
667 // Second pass. Find the latest setter method which |
668 // has the same type as the getter method. |
668 // has the same type as the getter method. |
669 for (int i = 0; i < list.size(); i++) { |
669 for (int i = 0; i < list.size(); i++) { |
670 pd = (PropertyDescriptor)list.get(i); |
670 pd = list.get(i); |
671 if (pd instanceof IndexedPropertyDescriptor) { |
671 if (pd instanceof IndexedPropertyDescriptor) { |
672 ipd = (IndexedPropertyDescriptor)pd; |
672 ipd = (IndexedPropertyDescriptor)pd; |
673 if (ipd.getIndexedWriteMethod() != null) { |
673 if (ipd.getIndexedWriteMethod() != null) { |
674 if (igpd != null) { |
674 if (igpd != null) { |
675 if (igpd.getIndexedPropertyType() |
675 if (igpd.getIndexedPropertyType() |
802 */ |
802 */ |
803 private PropertyDescriptor mergePropertyDescriptor(IndexedPropertyDescriptor ipd, |
803 private PropertyDescriptor mergePropertyDescriptor(IndexedPropertyDescriptor ipd, |
804 PropertyDescriptor pd) { |
804 PropertyDescriptor pd) { |
805 PropertyDescriptor result = null; |
805 PropertyDescriptor result = null; |
806 |
806 |
807 Class propType = pd.getPropertyType(); |
807 Class<?> propType = pd.getPropertyType(); |
808 Class ipropType = ipd.getIndexedPropertyType(); |
808 Class<?> ipropType = ipd.getIndexedPropertyType(); |
809 |
809 |
810 if (propType.isArray() && propType.getComponentType() == ipropType) { |
810 if (propType.isArray() && propType.getComponentType() == ipropType) { |
811 if (pd.getClass0().isAssignableFrom(ipd.getClass0())) { |
811 if (pd.getClass0().isAssignableFrom(ipd.getClass0())) { |
812 result = new IndexedPropertyDescriptor(pd, ipd); |
812 result = new IndexedPropertyDescriptor(pd, ipd); |
813 } else { |
813 } else { |
837 } |
837 } |
838 } |
838 } |
839 if (write == null && read != null) { |
839 if (write == null && read != null) { |
840 write = findMethod(result.getClass0(), |
840 write = findMethod(result.getClass0(), |
841 SET_PREFIX + NameGenerator.capitalize(result.getName()), 1, |
841 SET_PREFIX + NameGenerator.capitalize(result.getName()), 1, |
842 new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) }); |
842 new Class<?>[] { FeatureDescriptor.getReturnType(result.getClass0(), read) }); |
843 if (write != null) { |
843 if (write != null) { |
844 try { |
844 try { |
845 result.setWriteMethod(write); |
845 result.setWriteMethod(write); |
846 } catch (IntrospectionException ex) { |
846 } catch (IntrospectionException ex) { |
847 // no consequences for failure. |
847 // no consequences for failure. |
877 * @return An array of EventSetDescriptors describing the kinds of |
877 * @return An array of EventSetDescriptors describing the kinds of |
878 * events fired by the target bean. |
878 * events fired by the target bean. |
879 */ |
879 */ |
880 private EventSetDescriptor[] getTargetEventInfo() throws IntrospectionException { |
880 private EventSetDescriptor[] getTargetEventInfo() throws IntrospectionException { |
881 if (events == null) { |
881 if (events == null) { |
882 events = new HashMap(); |
882 events = new HashMap<>(); |
883 } |
883 } |
884 |
884 |
885 // Check if the bean has its own BeanInfo that will provide |
885 // Check if the bean has its own BeanInfo that will provide |
886 // explicit information. |
886 // explicit information. |
887 EventSetDescriptor[] explicitEvents = null; |
887 EventSetDescriptor[] explicitEvents = null; |
928 Method methodList[] = getPublicDeclaredMethods(beanClass); |
928 Method methodList[] = getPublicDeclaredMethods(beanClass); |
929 |
929 |
930 // Find all suitable "add", "remove" and "get" Listener methods |
930 // Find all suitable "add", "remove" and "get" Listener methods |
931 // The name of the listener type is the key for these hashtables |
931 // The name of the listener type is the key for these hashtables |
932 // i.e, ActionListener |
932 // i.e, ActionListener |
933 Map adds = null; |
933 Map<String, Method> adds = null; |
934 Map removes = null; |
934 Map<String, Method> removes = null; |
935 Map gets = null; |
935 Map<String, Method> gets = null; |
936 |
936 |
937 for (int i = 0; i < methodList.length; i++) { |
937 for (int i = 0; i < methodList.length; i++) { |
938 Method method = methodList[i]; |
938 Method method = methodList[i]; |
939 if (method == null) { |
939 if (method == null) { |
940 continue; |
940 continue; |
949 if (!name.startsWith(ADD_PREFIX) && !name.startsWith(REMOVE_PREFIX) |
949 if (!name.startsWith(ADD_PREFIX) && !name.startsWith(REMOVE_PREFIX) |
950 && !name.startsWith(GET_PREFIX)) { |
950 && !name.startsWith(GET_PREFIX)) { |
951 continue; |
951 continue; |
952 } |
952 } |
953 |
953 |
954 Class argTypes[] = FeatureDescriptor.getParameterTypes(beanClass, method); |
954 Class<?>[] argTypes = FeatureDescriptor.getParameterTypes(beanClass, method); |
955 Class resultType = FeatureDescriptor.getReturnType(beanClass, method); |
955 Class<?> resultType = FeatureDescriptor.getReturnType(beanClass, method); |
956 |
956 |
957 if (name.startsWith(ADD_PREFIX) && argTypes.length == 1 && |
957 if (name.startsWith(ADD_PREFIX) && argTypes.length == 1 && |
958 resultType == Void.TYPE && |
958 resultType == Void.TYPE && |
959 Introspector.isSubclass(argTypes[0], eventListenerType)) { |
959 Introspector.isSubclass(argTypes[0], eventListenerType)) { |
960 String listenerName = name.substring(3); |
960 String listenerName = name.substring(3); |
961 if (listenerName.length() > 0 && |
961 if (listenerName.length() > 0 && |
962 argTypes[0].getName().endsWith(listenerName)) { |
962 argTypes[0].getName().endsWith(listenerName)) { |
963 if (adds == null) { |
963 if (adds == null) { |
964 adds = new HashMap(); |
964 adds = new HashMap<>(); |
965 } |
965 } |
966 adds.put(listenerName, method); |
966 adds.put(listenerName, method); |
967 } |
967 } |
968 } |
968 } |
969 else if (name.startsWith(REMOVE_PREFIX) && argTypes.length == 1 && |
969 else if (name.startsWith(REMOVE_PREFIX) && argTypes.length == 1 && |
971 Introspector.isSubclass(argTypes[0], eventListenerType)) { |
971 Introspector.isSubclass(argTypes[0], eventListenerType)) { |
972 String listenerName = name.substring(6); |
972 String listenerName = name.substring(6); |
973 if (listenerName.length() > 0 && |
973 if (listenerName.length() > 0 && |
974 argTypes[0].getName().endsWith(listenerName)) { |
974 argTypes[0].getName().endsWith(listenerName)) { |
975 if (removes == null) { |
975 if (removes == null) { |
976 removes = new HashMap(); |
976 removes = new HashMap<>(); |
977 } |
977 } |
978 removes.put(listenerName, method); |
978 removes.put(listenerName, method); |
979 } |
979 } |
980 } |
980 } |
981 else if (name.startsWith(GET_PREFIX) && argTypes.length == 0 && |
981 else if (name.startsWith(GET_PREFIX) && argTypes.length == 0 && |
984 eventListenerType)) { |
984 eventListenerType)) { |
985 String listenerName = name.substring(3, name.length() - 1); |
985 String listenerName = name.substring(3, name.length() - 1); |
986 if (listenerName.length() > 0 && |
986 if (listenerName.length() > 0 && |
987 resultType.getComponentType().getName().endsWith(listenerName)) { |
987 resultType.getComponentType().getName().endsWith(listenerName)) { |
988 if (gets == null) { |
988 if (gets == null) { |
989 gets = new HashMap(); |
989 gets = new HashMap<>(); |
990 } |
990 } |
991 gets.put(listenerName, method); |
991 gets.put(listenerName, method); |
992 } |
992 } |
993 } |
993 } |
994 } |
994 } |
995 |
995 |
996 if (adds != null && removes != null) { |
996 if (adds != null && removes != null) { |
997 // Now look for matching addFooListener+removeFooListener pairs. |
997 // Now look for matching addFooListener+removeFooListener pairs. |
998 // Bonus if there is a matching getFooListeners method as well. |
998 // Bonus if there is a matching getFooListeners method as well. |
999 Iterator keys = adds.keySet().iterator(); |
999 Iterator<String> keys = adds.keySet().iterator(); |
1000 while (keys.hasNext()) { |
1000 while (keys.hasNext()) { |
1001 String listenerName = (String) keys.next(); |
1001 String listenerName = keys.next(); |
1002 // Skip any "add" which doesn't have a matching "remove" or |
1002 // Skip any "add" which doesn't have a matching "remove" or |
1003 // a listener name that doesn't end with Listener |
1003 // a listener name that doesn't end with Listener |
1004 if (removes.get(listenerName) == null || !listenerName.endsWith("Listener")) { |
1004 if (removes.get(listenerName) == null || !listenerName.endsWith("Listener")) { |
1005 continue; |
1005 continue; |
1006 } |
1006 } |
1007 String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8)); |
1007 String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8)); |
1008 Method addMethod = (Method)adds.get(listenerName); |
1008 Method addMethod = adds.get(listenerName); |
1009 Method removeMethod = (Method)removes.get(listenerName); |
1009 Method removeMethod = removes.get(listenerName); |
1010 Method getMethod = null; |
1010 Method getMethod = null; |
1011 if (gets != null) { |
1011 if (gets != null) { |
1012 getMethod = (Method)gets.get(listenerName); |
1012 getMethod = gets.get(listenerName); |
1013 } |
1013 } |
1014 Class argType = FeatureDescriptor.getParameterTypes(beanClass, addMethod)[0]; |
1014 Class<?> argType = FeatureDescriptor.getParameterTypes(beanClass, addMethod)[0]; |
1015 |
1015 |
1016 // generate a list of Method objects for each of the target methods: |
1016 // generate a list of Method objects for each of the target methods: |
1017 Method allMethods[] = getPublicDeclaredMethods(argType); |
1017 Method allMethods[] = getPublicDeclaredMethods(argType); |
1018 List validMethods = new ArrayList(allMethods.length); |
1018 List<Method> validMethods = new ArrayList<>(allMethods.length); |
1019 for (int i = 0; i < allMethods.length; i++) { |
1019 for (int i = 0; i < allMethods.length; i++) { |
1020 if (allMethods[i] == null) { |
1020 if (allMethods[i] == null) { |
1021 continue; |
1021 continue; |
1022 } |
1022 } |
1023 |
1023 |
1024 if (isEventHandler(allMethods[i])) { |
1024 if (isEventHandler(allMethods[i])) { |
1025 validMethods.add(allMethods[i]); |
1025 validMethods.add(allMethods[i]); |
1026 } |
1026 } |
1027 } |
1027 } |
1028 Method[] methods = (Method[])validMethods.toArray(new Method[validMethods.size()]); |
1028 Method[] methods = validMethods.toArray(new Method[validMethods.size()]); |
1029 |
1029 |
1030 EventSetDescriptor esd = new EventSetDescriptor(eventName, argType, |
1030 EventSetDescriptor esd = new EventSetDescriptor(eventName, argType, |
1031 methods, addMethod, |
1031 methods, addMethod, |
1032 removeMethod, |
1032 removeMethod, |
1033 getMethod); |
1033 getMethod); |
1046 if (events.size() == 0) { |
1046 if (events.size() == 0) { |
1047 result = EMPTY_EVENTSETDESCRIPTORS; |
1047 result = EMPTY_EVENTSETDESCRIPTORS; |
1048 } else { |
1048 } else { |
1049 // Allocate and populate the result array. |
1049 // Allocate and populate the result array. |
1050 result = new EventSetDescriptor[events.size()]; |
1050 result = new EventSetDescriptor[events.size()]; |
1051 result = (EventSetDescriptor[])events.values().toArray(result); |
1051 result = events.values().toArray(result); |
1052 |
1052 |
1053 // Set the default index. |
1053 // Set the default index. |
1054 if (defaultEventName != null) { |
1054 if (defaultEventName != null) { |
1055 for (int i = 0; i < result.length; i++) { |
1055 for (int i = 0; i < result.length; i++) { |
1056 if (defaultEventName.equals(result[i].getName())) { |
1056 if (defaultEventName.equals(result[i].getName())) { |
1065 private void addEvent(EventSetDescriptor esd) { |
1065 private void addEvent(EventSetDescriptor esd) { |
1066 String key = esd.getName(); |
1066 String key = esd.getName(); |
1067 if (esd.getName().equals("propertyChange")) { |
1067 if (esd.getName().equals("propertyChange")) { |
1068 propertyChangeSource = true; |
1068 propertyChangeSource = true; |
1069 } |
1069 } |
1070 EventSetDescriptor old = (EventSetDescriptor)events.get(key); |
1070 EventSetDescriptor old = events.get(key); |
1071 if (old == null) { |
1071 if (old == null) { |
1072 events.put(key, esd); |
1072 events.put(key, esd); |
1073 return; |
1073 return; |
1074 } |
1074 } |
1075 EventSetDescriptor composite = new EventSetDescriptor(old, esd); |
1075 EventSetDescriptor composite = new EventSetDescriptor(old, esd); |
1080 * @return An array of MethodDescriptors describing the private |
1080 * @return An array of MethodDescriptors describing the private |
1081 * methods supported by the target bean. |
1081 * methods supported by the target bean. |
1082 */ |
1082 */ |
1083 private MethodDescriptor[] getTargetMethodInfo() { |
1083 private MethodDescriptor[] getTargetMethodInfo() { |
1084 if (methods == null) { |
1084 if (methods == null) { |
1085 methods = new HashMap(100); |
1085 methods = new HashMap<>(100); |
1086 } |
1086 } |
1087 |
1087 |
1088 // Check if the bean has its own BeanInfo that will provide |
1088 // Check if the bean has its own BeanInfo that will provide |
1089 // explicit information. |
1089 // explicit information. |
1090 MethodDescriptor[] explicitMethods = null; |
1090 MethodDescriptor[] explicitMethods = null; |
1133 } |
1133 } |
1134 } |
1134 } |
1135 |
1135 |
1136 // Allocate and populate the result array. |
1136 // Allocate and populate the result array. |
1137 MethodDescriptor result[] = new MethodDescriptor[methods.size()]; |
1137 MethodDescriptor result[] = new MethodDescriptor[methods.size()]; |
1138 result = (MethodDescriptor[])methods.values().toArray(result); |
1138 result = methods.values().toArray(result); |
1139 |
1139 |
1140 return result; |
1140 return result; |
1141 } |
1141 } |
1142 |
1142 |
1143 private void addMethod(MethodDescriptor md) { |
1143 private void addMethod(MethodDescriptor md) { |
1144 // We have to be careful here to distinguish method by both name |
1144 // We have to be careful here to distinguish method by both name |
1145 // and argument lists. |
1145 // and argument lists. |
1146 // This method gets called a *lot, so we try to be efficient. |
1146 // This method gets called a *lot, so we try to be efficient. |
1147 String name = md.getName(); |
1147 String name = md.getName(); |
1148 |
1148 |
1149 MethodDescriptor old = (MethodDescriptor)methods.get(name); |
1149 MethodDescriptor old = methods.get(name); |
1150 if (old == null) { |
1150 if (old == null) { |
1151 // This is the common case. |
1151 // This is the common case. |
1152 methods.put(name, md); |
1152 methods.put(name, md); |
1153 return; |
1153 return; |
1154 } |
1154 } |
1177 |
1177 |
1178 // We have a collision on method names with different type signatures. |
1178 // We have a collision on method names with different type signatures. |
1179 // This is very rare. |
1179 // This is very rare. |
1180 |
1180 |
1181 String longKey = makeQualifiedMethodName(name, p1); |
1181 String longKey = makeQualifiedMethodName(name, p1); |
1182 old = (MethodDescriptor)methods.get(longKey); |
1182 old = methods.get(longKey); |
1183 if (old == null) { |
1183 if (old == null) { |
1184 methods.put(longKey, md); |
1184 methods.put(longKey, md); |
1185 return; |
1185 return; |
1186 } |
1186 } |
1187 MethodDescriptor composite = new MethodDescriptor(old, md); |
1187 MethodDescriptor composite = new MethodDescriptor(old, md); |
1278 |
1278 |
1279 /** |
1279 /** |
1280 * Internal support for finding a target methodName with a given |
1280 * Internal support for finding a target methodName with a given |
1281 * parameter list on a given class. |
1281 * parameter list on a given class. |
1282 */ |
1282 */ |
1283 private static Method internalFindMethod(Class start, String methodName, |
1283 private static Method internalFindMethod(Class<?> start, String methodName, |
1284 int argCount, Class args[]) { |
1284 int argCount, Class args[]) { |
1285 // For overriden methods we need to find the most derived version. |
1285 // For overriden methods we need to find the most derived version. |
1286 // So we start with the given class and walk up the superclass chain. |
1286 // So we start with the given class and walk up the superclass chain. |
1287 |
1287 |
1288 Method method = null; |
1288 Method method = null; |
1289 |
1289 |
1290 for (Class cl = start; cl != null; cl = cl.getSuperclass()) { |
1290 for (Class<?> cl = start; cl != null; cl = cl.getSuperclass()) { |
1291 Method methods[] = getPublicDeclaredMethods(cl); |
1291 Method methods[] = getPublicDeclaredMethods(cl); |
1292 for (int i = 0; i < methods.length; i++) { |
1292 for (int i = 0; i < methods.length; i++) { |
1293 method = methods[i]; |
1293 method = methods[i]; |
1294 if (method == null) { |
1294 if (method == null) { |
1295 continue; |
1295 continue; |
1352 * @param methodName Name of the method. |
1352 * @param methodName Name of the method. |
1353 * @param argCount Number of arguments for the desired method. |
1353 * @param argCount Number of arguments for the desired method. |
1354 * @param args Array of argument types for the method. |
1354 * @param args Array of argument types for the method. |
1355 * @return the method or null if not found |
1355 * @return the method or null if not found |
1356 */ |
1356 */ |
1357 static Method findMethod(Class cls, String methodName, int argCount, |
1357 static Method findMethod(Class<?> cls, String methodName, int argCount, |
1358 Class args[]) { |
1358 Class args[]) { |
1359 if (methodName == null) { |
1359 if (methodName == null) { |
1360 return null; |
1360 return null; |
1361 } |
1361 } |
1362 return internalFindMethod(cls, methodName, argCount, args); |
1362 return internalFindMethod(cls, methodName, argCount, args); |
1366 * Return true if class a is either equivalent to class b, or |
1366 * Return true if class a is either equivalent to class b, or |
1367 * if class a is a subclass of class b, i.e. if a either "extends" |
1367 * if class a is a subclass of class b, i.e. if a either "extends" |
1368 * or "implements" b. |
1368 * or "implements" b. |
1369 * Note tht either or both "Class" objects may represent interfaces. |
1369 * Note tht either or both "Class" objects may represent interfaces. |
1370 */ |
1370 */ |
1371 static boolean isSubclass(Class a, Class b) { |
1371 static boolean isSubclass(Class<?> a, Class<?> b) { |
1372 // We rely on the fact that for any given java class or |
1372 // We rely on the fact that for any given java class or |
1373 // primtitive type there is a unqiue Class object, so |
1373 // primtitive type there is a unqiue Class object, so |
1374 // we can use object equivalence in the comparisons. |
1374 // we can use object equivalence in the comparisons. |
1375 if (a == b) { |
1375 if (a == b) { |
1376 return true; |
1376 return true; |
1377 } |
1377 } |
1378 if (a == null || b == null) { |
1378 if (a == null || b == null) { |
1379 return false; |
1379 return false; |
1380 } |
1380 } |
1381 for (Class x = a; x != null; x = x.getSuperclass()) { |
1381 for (Class<?> x = a; x != null; x = x.getSuperclass()) { |
1382 if (x == b) { |
1382 if (x == b) { |
1383 return true; |
1383 return true; |
1384 } |
1384 } |
1385 if (b.isInterface()) { |
1385 if (b.isInterface()) { |
1386 Class interfaces[] = x.getInterfaces(); |
1386 Class<?>[] interfaces = x.getInterfaces(); |
1387 for (int i = 0; i < interfaces.length; i++) { |
1387 for (int i = 0; i < interfaces.length; i++) { |
1388 if (isSubclass(interfaces[i], b)) { |
1388 if (isSubclass(interfaces[i], b)) { |
1389 return true; |
1389 return true; |
1390 } |
1390 } |
1391 } |
1391 } |
1410 /** |
1410 /** |
1411 * Try to create an instance of a named class. |
1411 * Try to create an instance of a named class. |
1412 * First try the classloader of "sibling", then try the system |
1412 * First try the classloader of "sibling", then try the system |
1413 * classloader then the class loader of the current Thread. |
1413 * classloader then the class loader of the current Thread. |
1414 */ |
1414 */ |
1415 static Object instantiate(Class sibling, String className) |
1415 static Object instantiate(Class<?> sibling, String className) |
1416 throws InstantiationException, IllegalAccessException, |
1416 throws InstantiationException, IllegalAccessException, |
1417 ClassNotFoundException { |
1417 ClassNotFoundException { |
1418 // First check with sibling's classloader (if any). |
1418 // First check with sibling's classloader (if any). |
1419 ClassLoader cl = sibling.getClassLoader(); |
1419 ClassLoader cl = sibling.getClassLoader(); |
1420 Class cls = ClassFinder.findClass(className, cl); |
1420 Class<?> cls = ClassFinder.findClass(className, cl); |
1421 return cls.newInstance(); |
1421 return cls.newInstance(); |
1422 } |
1422 } |
1423 |
1423 |
1424 } // end class Introspector |
1424 } // end class Introspector |
1425 |
1425 |
1450 this.events = events; |
1450 this.events = events; |
1451 this.defaultEvent = defaultEvent; |
1451 this.defaultEvent = defaultEvent; |
1452 this.properties = properties; |
1452 this.properties = properties; |
1453 this.defaultProperty = defaultProperty; |
1453 this.defaultProperty = defaultProperty; |
1454 this.methods = methods; |
1454 this.methods = methods; |
1455 this.targetBeanInfoRef = new SoftReference<BeanInfo>(targetBeanInfo); |
1455 this.targetBeanInfoRef = new SoftReference<>(targetBeanInfo); |
1456 } |
1456 } |
1457 |
1457 |
1458 /** |
1458 /** |
1459 * Package-private dup constructor |
1459 * Package-private dup constructor |
1460 * This must isolate the new object from any changes to the old object. |
1460 * This must isolate the new object from any changes to the old object. |