44 |
import gnu.java.lang.*; |
import gnu.java.lang.*; |
45 |
|
|
46 |
/** |
/** |
47 |
** Introspector is the class that does the bulk of the |
* Introspector is the class that does the bulk of the |
48 |
** design-time work in Java Beans. Every class must have |
* design-time work in Java Beans. Every class must have |
49 |
** a BeanInfo in order for an RAD tool to use it; but, as |
* a BeanInfo in order for an RAD tool to use it; but, as |
50 |
** promised, you don't have to write the BeanInfo class |
* promised, you don't have to write the BeanInfo class |
51 |
** yourself if you don't want to. All you have to do is |
* yourself if you don't want to. All you have to do is |
52 |
** call getBeanInfo() in the Introspector and it will use |
* call getBeanInfo() in the Introspector and it will use |
53 |
** standard JavaBeans-defined method signatures to |
* standard JavaBeans-defined method signatures to |
54 |
** determine the information about your class.<P> |
* determine the information about your class.<P> |
55 |
** |
* |
56 |
** Don't worry about it too much, though: you can provide |
* Don't worry about it too much, though: you can provide |
57 |
** JavaBeans with as much customized information as you |
* JavaBeans with as much customized information as you |
58 |
** want, or as little as you want, using the BeanInfo |
* want, or as little as you want, using the BeanInfo |
59 |
** interface (see BeanInfo for details).<P> |
* interface (see BeanInfo for details).<P> |
60 |
** |
* |
61 |
** <STRONG>Order of Operations</STRONG><P> |
* <STRONG>Order of Operations</STRONG><P> |
62 |
** |
* |
63 |
** When you call getBeanInfo(class c), the Introspector |
* When you call getBeanInfo(class c), the Introspector |
64 |
** first searches for BeanInfo class to see if you |
* first searches for BeanInfo class to see if you |
65 |
** provided any explicit information. It searches for a |
* provided any explicit information. It searches for a |
66 |
** class named <bean class name>BeanInfo in different |
* class named <bean class name>BeanInfo in different |
67 |
** packages, first searching the bean class's package |
* packages, first searching the bean class's package |
68 |
** and then moving on to search the beanInfoSearchPath.<P> |
* and then moving on to search the beanInfoSearchPath.<P> |
69 |
** |
* |
70 |
** If it does not find a BeanInfo class, it acts as though |
* If it does not find a BeanInfo class, it acts as though |
71 |
** it had found a BeanInfo class returning null from all |
* it had found a BeanInfo class returning null from all |
72 |
** methods (meaning it should discover everything through |
* methods (meaning it should discover everything through |
73 |
** Introspection). If it does, then it takes the |
* Introspection). If it does, then it takes the |
74 |
** information it finds in the BeanInfo class to be |
* information it finds in the BeanInfo class to be |
75 |
** canonical (that is, the information speaks for its |
* canonical (that is, the information speaks for its |
76 |
** class as well as all superclasses).<P> |
* class as well as all superclasses).<P> |
77 |
** |
* |
78 |
** When it has introspected the class, calls |
* When it has introspected the class, calls |
79 |
** getBeanInfo(c.getSuperclass) and adds that information |
* getBeanInfo(c.getSuperclass) and adds that information |
80 |
** to the information it has, not adding to any information |
* to the information it has, not adding to any information |
81 |
** it already has that is canonical.<P> |
* it already has that is canonical.<P> |
82 |
** |
* |
83 |
** <STRONG>Introspection Design Patterns</STRONG><P> |
* <STRONG>Introspection Design Patterns</STRONG><P> |
84 |
** |
* |
85 |
** When the Introspector goes in to read the class, it |
* When the Introspector goes in to read the class, it |
86 |
** follows a well-defined order in order to not leave any |
* follows a well-defined order in order to not leave any |
87 |
** methods unaccounted for. Its job is to step over all |
* methods unaccounted for. Its job is to step over all |
88 |
** of the public methods in a class and determine whether |
* of the public methods in a class and determine whether |
89 |
** they are part of a property, an event, or a method (in |
* they are part of a property, an event, or a method (in |
90 |
** that order). |
* that order). |
91 |
** |
* |
92 |
** |
* |
93 |
** <STRONG>Properties:</STRONG><P> |
* <STRONG>Properties:</STRONG><P> |
94 |
** |
* |
95 |
** <OL> |
* <OL> |
96 |
** <LI>If there is a <CODE>public boolean isXXX()</CODE> |
* <LI>If there is a <CODE>public boolean isXXX()</CODE> |
97 |
** method, then XXX is a read-only boolean property. |
* method, then XXX is a read-only boolean property. |
98 |
** <CODE>boolean getXXX()</CODE> may be supplied in |
* <CODE>boolean getXXX()</CODE> may be supplied in |
99 |
** addition to this method, although isXXX() is the |
* addition to this method, although isXXX() is the |
100 |
** one that will be used in this case and getXXX() |
* one that will be used in this case and getXXX() |
101 |
** will be ignored. If there is a |
* will be ignored. If there is a |
102 |
** <CODE>public void setXXX(boolean)</CODE> method, |
* <CODE>public void setXXX(boolean)</CODE> method, |
103 |
** it is part of this group and makes it a read-write |
* it is part of this group and makes it a read-write |
104 |
** property.</LI> |
* property.</LI> |
105 |
** <LI>If there is a |
* <LI>If there is a |
106 |
** <CODE>public <type> getXXX(int)</CODE> |
* <CODE>public <type> getXXX(int)</CODE> |
107 |
** method, then XXX is a read-only indexed property of |
* method, then XXX is a read-only indexed property of |
108 |
** type <type>. If there is a |
* type <type>. If there is a |
109 |
** <CODE>public void setXXX(int,<type>)</CODE> |
* <CODE>public void setXXX(int,<type>)</CODE> |
110 |
** method, then it is a read-write indexed property of |
* method, then it is a read-write indexed property of |
111 |
** type <type>. There may also be a |
* type <type>. There may also be a |
112 |
** <CODE>public <type>[] getXXX()</CODE> and a |
* <CODE>public <type>[] getXXX()</CODE> and a |
113 |
** <CODE>public void setXXX(<type>)</CODE> |
* <CODE>public void setXXX(<type>)</CODE> |
114 |
** method as well.</CODE></LI> |
* method as well.</CODE></LI> |
115 |
** <LI>If there is a |
* <LI>If there is a |
116 |
** <CODE>public void setXXX(int,<type>)</CODE> |
* <CODE>public void setXXX(int,<type>)</CODE> |
117 |
** method, then it is a write-only indexed property of |
* method, then it is a write-only indexed property of |
118 |
** type <type>. There may also be a |
* type <type>. There may also be a |
119 |
** <CODE>public <type>[] getXXX()</CODE> and a |
* <CODE>public <type>[] getXXX()</CODE> and a |
120 |
** <CODE>public void setXXX(<type>)</CODE> |
* <CODE>public void setXXX(<type>)</CODE> |
121 |
** method as well.</CODE></LI> |
* method as well.</CODE></LI> |
122 |
** <LI>If there is a |
* <LI>If there is a |
123 |
** <CODE>public <type> getXXX()</CODE> method, |
* <CODE>public <type> getXXX()</CODE> method, |
124 |
** then XXX is a read-only property of type |
* then XXX is a read-only property of type |
125 |
** <type>. If there is a |
* <type>. If there is a |
126 |
** <CODE>public void setXXX(<type>)</CODE> |
* <CODE>public void setXXX(<type>)</CODE> |
127 |
** method, then it will be used for the property and |
* method, then it will be used for the property and |
128 |
** the property will be considered read-write.</LI> |
* the property will be considered read-write.</LI> |
129 |
** <LI>If there is a |
* <LI>If there is a |
130 |
** <CODE>public void setXXX(<type>)</CODE> |
* <CODE>public void setXXX(<type>)</CODE> |
131 |
** method, then as long as XXX is not already used as |
* method, then as long as XXX is not already used as |
132 |
** the name of a property, XXX is assumed to be a |
* the name of a property, XXX is assumed to be a |
133 |
** write-only property of type <type>.</LI> |
* write-only property of type <type>.</LI> |
134 |
** <LI>In all of the above cases, if the setXXX() method |
* <LI>In all of the above cases, if the setXXX() method |
135 |
** throws <CODE>PropertyVetoException</CODE>, then the |
* throws <CODE>PropertyVetoException</CODE>, then the |
136 |
** property in question is assumed to be constrained. |
* property in question is assumed to be constrained. |
137 |
** No properties are ever assumed to be bound |
* No properties are ever assumed to be bound |
138 |
** (<STRONG>Spec Note:</STRONG> this is not in the |
* (<STRONG>Spec Note:</STRONG> this is not in the |
139 |
** spec, it just makes sense). See PropertyDescriptor |
* spec, it just makes sense). See PropertyDescriptor |
140 |
** for a description of bound and constrained |
* for a description of bound and constrained |
141 |
** properties.</LI> |
* properties.</LI> |
142 |
** </OL> |
* </OL> |
143 |
** |
* |
144 |
** <STRONG>Events:</STRONG><P> |
* <STRONG>Events:</STRONG><P> |
145 |
** |
* |
146 |
** If there is a pair of methods, |
* If there is a pair of methods, |
147 |
** <CODE>public void addXXX(<type>)</CODE> and |
* <CODE>public void addXXX(<type>)</CODE> and |
148 |
** <CODE>public void removeXXX(<type>)</CODE>, where |
* <CODE>public void removeXXX(<type>)</CODE>, where |
149 |
** <type> is a descendant of |
* <type> is a descendant of |
150 |
** <CODE>java.util.EventListener</CODE>, then the pair of |
* <CODE>java.util.EventListener</CODE>, then the pair of |
151 |
** methods imply that this Bean will fire events to |
* methods imply that this Bean will fire events to |
152 |
** listeners of type <type>.<P> |
* listeners of type <type>.<P> |
153 |
** |
* |
154 |
** If the addXXX() method throws |
* If the addXXX() method throws |
155 |
** <CODE>java.util.TooManyListenersException</CODE>, then |
* <CODE>java.util.TooManyListenersException</CODE>, then |
156 |
** the event set is assumed to be <EM>unicast</EM>. See |
* the event set is assumed to be <EM>unicast</EM>. See |
157 |
** EventSetDescriptor for a discussion of unicast event |
* EventSetDescriptor for a discussion of unicast event |
158 |
** sets.<P> |
* sets.<P> |
159 |
** |
* |
160 |
** <STRONG>Spec Note:</STRONG> the spec seems to say that |
* <STRONG>Spec Note:</STRONG> the spec seems to say that |
161 |
** the listener type's classname must be equal to the XXX |
* the listener type's classname must be equal to the XXX |
162 |
** part of addXXX() and removeXXX(), but that is not the |
* part of addXXX() and removeXXX(), but that is not the |
163 |
** case in Sun's implementation, so I am assuming it is |
* case in Sun's implementation, so I am assuming it is |
164 |
** not the case in general.<P> |
* not the case in general.<P> |
165 |
** |
* |
166 |
** <STRONG>Methods:</STRONG><P> |
* <STRONG>Methods:</STRONG><P> |
167 |
** |
* |
168 |
** Any public methods (including those which were used |
* Any public methods (including those which were used |
169 |
** for Properties or Events) are used as Methods. |
* for Properties or Events) are used as Methods. |
170 |
** |
* |
171 |
** @author John Keiser |
* @author John Keiser |
172 |
** @since JDK1.1 |
* @since JDK1.1 |
173 |
** @version 1.1.0, 29 Jul 1998 |
* @version 1.1.0, 29 Jul 1998 |
174 |
** @see java.beans.BeanInfo |
* @see java.beans.BeanInfo |
175 |
**/ |
*/ |
|
|
|
176 |
public class Introspector { |
public class Introspector { |
177 |
static String[] beanInfoSearchPath = {"gnu.java.beans.info"}; |
static String[] beanInfoSearchPath = {"gnu.java.beans.info"}; |
178 |
static Hashtable beanInfoCache = new Hashtable(); |
static Hashtable beanInfoCache = new Hashtable(); |
179 |
|
|
180 |
private Introspector() {} |
private Introspector() {} |
181 |
|
|
182 |
/** Get the BeanInfo for class <CODE>beanClass</CODE>, |
/** |
183 |
** first by looking for explicit information, next by |
* Get the BeanInfo for class <CODE>beanClass</CODE>, |
184 |
** using standard design patterns to determine |
* first by looking for explicit information, next by |
185 |
** information about the class. |
* using standard design patterns to determine |
186 |
** @param beanClass the class to get BeanInfo about. |
* information about the class. |
187 |
** @return the BeanInfo object representing the class. |
* |
188 |
**/ |
* @param beanClass the class to get BeanInfo about. |
189 |
public static BeanInfo getBeanInfo(Class beanClass) throws IntrospectionException { |
* @return the BeanInfo object representing the class. |
190 |
BeanInfo cachedInfo; |
*/ |
191 |
synchronized(beanClass) { |
public static BeanInfo getBeanInfo(Class beanClass) |
192 |
cachedInfo = (BeanInfo)beanInfoCache.get(beanClass); |
throws IntrospectionException |
193 |
if(cachedInfo != null) { |
{ |
194 |
return cachedInfo; |
BeanInfo cachedInfo; |
195 |
} |
synchronized(beanClass) |
196 |
cachedInfo = getBeanInfo(beanClass,null); |
{ |
197 |
beanInfoCache.put(beanClass,cachedInfo); |
cachedInfo = (BeanInfo)beanInfoCache.get(beanClass); |
198 |
return cachedInfo; |
if(cachedInfo != null) |
199 |
} |
{ |
200 |
} |
return cachedInfo; |
201 |
|
} |
202 |
/** Get the BeanInfo for class <CODE>beanClass</CODE>, |
cachedInfo = getBeanInfo(beanClass,null); |
203 |
** first by looking for explicit information, next by |
beanInfoCache.put(beanClass,cachedInfo); |
204 |
** using standard design patterns to determine |
return cachedInfo; |
205 |
** information about the class. It crawls up the |
} |
206 |
** inheritance tree until it hits <CODE>topClass</CODE>. |
} |
207 |
** @param beanClass the Bean class. |
|
208 |
** @param stopClass the class to stop at. |
/** |
209 |
** @return the BeanInfo object representing the class. |
* Get the BeanInfo for class <CODE>beanClass</CODE>, |
210 |
**/ |
* first by looking for explicit information, next by |
211 |
public static BeanInfo getBeanInfo(Class beanClass, Class stopClass) throws IntrospectionException { |
* using standard design patterns to determine |
212 |
ExplicitInfo explicit = new ExplicitInfo(beanClass,stopClass); |
* information about the class. It crawls up the |
213 |
|
* inheritance tree until it hits <CODE>topClass</CODE>. |
214 |
IntrospectionIncubator ii = new IntrospectionIncubator(); |
* |
215 |
ii.setPropertyStopClass(explicit.propertyStopClass); |
* @param beanClass the Bean class. |
216 |
ii.setEventStopClass(explicit.eventStopClass); |
* @param stopClass the class to stop at. |
217 |
ii.setMethodStopClass(explicit.methodStopClass); |
* @return the BeanInfo object representing the class. |
218 |
ii.addMethods(beanClass.getMethods()); |
*/ |
219 |
|
public static BeanInfo getBeanInfo(Class beanClass, Class stopClass) |
220 |
BeanInfoEmbryo currentInfo = ii.getBeanInfoEmbryo(); |
throws IntrospectionException |
221 |
PropertyDescriptor[] p = explicit.explicitPropertyDescriptors; |
{ |
222 |
if(p!=null) { |
ExplicitInfo explicit = new ExplicitInfo(beanClass,stopClass); |
223 |
for(int i=0;i<p.length;i++) { |
|
224 |
if(!currentInfo.hasProperty(p[i])) { |
IntrospectionIncubator ii = new IntrospectionIncubator(); |
225 |
currentInfo.addProperty(p[i]); |
ii.setPropertyStopClass(explicit.propertyStopClass); |
226 |
} |
ii.setEventStopClass(explicit.eventStopClass); |
227 |
} |
ii.setMethodStopClass(explicit.methodStopClass); |
228 |
if(explicit.defaultProperty != -1) { |
ii.addMethods(beanClass.getMethods()); |
229 |
currentInfo.setDefaultPropertyName(p[explicit.defaultProperty].getName()); |
|
230 |
} |
BeanInfoEmbryo currentInfo = ii.getBeanInfoEmbryo(); |
231 |
} |
PropertyDescriptor[] p = explicit.explicitPropertyDescriptors; |
232 |
EventSetDescriptor[] e = explicit.explicitEventSetDescriptors; |
if(p!=null) |
233 |
if(e!=null) { |
{ |
234 |
for(int i=0;i<e.length;i++) { |
for(int i=0;i<p.length;i++) |
235 |
if(!currentInfo.hasEvent(e[i])) { |
{ |
236 |
currentInfo.addEvent(e[i]); |
if(!currentInfo.hasProperty(p[i])) |
237 |
} |
{ |
238 |
} |
currentInfo.addProperty(p[i]); |
239 |
if(explicit.defaultEvent != -1) { |
} |
240 |
currentInfo.setDefaultEventName(e[explicit.defaultEvent].getName()); |
} |
241 |
} |
if(explicit.defaultProperty != -1) |
242 |
} |
{ |
243 |
MethodDescriptor[] m = explicit.explicitMethodDescriptors; |
currentInfo.setDefaultPropertyName(p[explicit.defaultProperty].getName()); |
244 |
if(m!=null) { |
} |
245 |
for(int i=0;i<m.length;i++) { |
} |
246 |
if(!currentInfo.hasMethod(m[i])) { |
EventSetDescriptor[] e = explicit.explicitEventSetDescriptors; |
247 |
currentInfo.addMethod(m[i]); |
if(e!=null) |
248 |
} |
{ |
249 |
} |
for(int i=0;i<e.length;i++) |
250 |
} |
{ |
251 |
|
if(!currentInfo.hasEvent(e[i])) |
252 |
if(explicit.explicitBeanDescriptor != null) { |
{ |
253 |
currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,explicit.explicitBeanDescriptor.getCustomizerClass())); |
currentInfo.addEvent(e[i]); |
254 |
} else { |
} |
255 |
currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,null)); |
} |
256 |
} |
if(explicit.defaultEvent != -1) |
257 |
|
{ |
258 |
currentInfo.setAdditionalBeanInfo(explicit.explicitBeanInfo); |
currentInfo.setDefaultEventName(e[explicit.defaultEvent].getName()); |
259 |
currentInfo.setIcons(explicit.im); |
} |
260 |
|
} |
261 |
return currentInfo.getBeanInfo(); |
MethodDescriptor[] m = explicit.explicitMethodDescriptors; |
262 |
} |
if(m!=null) |
263 |
|
{ |
264 |
/** Get the search path for BeanInfo classes. |
for(int i=0;i<m.length;i++) |
265 |
** @return the BeanInfo search path. |
{ |
266 |
**/ |
if(!currentInfo.hasMethod(m[i])) |
267 |
public static String[] getBeanInfoSearchPath() { |
{ |
268 |
return beanInfoSearchPath; |
currentInfo.addMethod(m[i]); |
269 |
} |
} |
270 |
|
} |
271 |
/** Set the search path for BeanInfo classes. |
} |
272 |
** @param beanInfoSearchPath the new BeanInfo search |
|
273 |
** path. |
if(explicit.explicitBeanDescriptor != null) |
274 |
**/ |
{ |
275 |
public static void setBeanInfoSearchPath(String[] beanInfoSearchPath) { |
currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,explicit.explicitBeanDescriptor.getCustomizerClass())); |
276 |
Introspector.beanInfoSearchPath = beanInfoSearchPath; |
} |
277 |
} |
else |
278 |
|
{ |
279 |
/** A helper method to convert a name to standard Java |
currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,null)); |
280 |
** naming conventions: anything with two capitals as the |
} |
281 |
** first two letters remains the same, otherwise the |
|
282 |
** first letter is decapitalized. URL = URL, I = i, |
currentInfo.setAdditionalBeanInfo(explicit.explicitBeanInfo); |
283 |
** MyMethod = myMethod. |
currentInfo.setIcons(explicit.im); |
284 |
** @param name the name to decapitalize. |
|
285 |
** @return the decapitalized name. |
return currentInfo.getBeanInfo(); |
286 |
**/ |
} |
287 |
public static String decapitalize(String name) { |
|
288 |
try { |
/** |
289 |
if(!Character.isUpperCase(name.charAt(0))) { |
* Get the search path for BeanInfo classes. |
290 |
return name; |
* |
291 |
} else { |
* @return the BeanInfo search path. |
292 |
try { |
*/ |
293 |
if(Character.isUpperCase(name.charAt(1))) { |
public static String[] getBeanInfoSearchPath() |
294 |
return name; |
{ |
295 |
} else { |
return beanInfoSearchPath; |
296 |
char[] c = name.toCharArray(); |
} |
297 |
c[0] = Character.toLowerCase(c[0]); |
|
298 |
return new String(c); |
/** |
299 |
} |
* Set the search path for BeanInfo classes. |
300 |
} catch(StringIndexOutOfBoundsException E) { |
* @param beanInfoSearchPath the new BeanInfo search |
301 |
char[] c = new char[1]; |
* path. |
302 |
c[0] = Character.toLowerCase(name.charAt(0)); |
*/ |
303 |
return new String(c); |
public static void setBeanInfoSearchPath(String[] beanInfoSearchPath) |
304 |
} |
{ |
305 |
} |
Introspector.beanInfoSearchPath = beanInfoSearchPath; |
306 |
} catch(StringIndexOutOfBoundsException E) { |
} |
307 |
return name; |
|
308 |
} catch(NullPointerException E) { |
/** |
309 |
return null; |
* A helper method to convert a name to standard Java |
310 |
} |
* naming conventions: anything with two capitals as the |
311 |
} |
* first two letters remains the same, otherwise the |
312 |
|
* first letter is decapitalized. URL = URL, I = i, |
313 |
static BeanInfo copyBeanInfo(BeanInfo b) { |
* MyMethod = myMethod. |
314 |
java.awt.Image[] icons = new java.awt.Image[4]; |
* |
315 |
for(int i=1;i<=4;i++) { |
* @param name the name to decapitalize. |
316 |
icons[i-1] = b.getIcon(i); |
* @return the decapitalized name. |
317 |
} |
*/ |
318 |
return new ExplicitBeanInfo(b.getBeanDescriptor(),b.getAdditionalBeanInfo(), |
public static String decapitalize(String name) |
319 |
b.getPropertyDescriptors(),b.getDefaultPropertyIndex(), |
{ |
320 |
b.getEventSetDescriptors(),b.getDefaultEventIndex(), |
try |
321 |
b.getMethodDescriptors(),icons); |
{ |
322 |
|
if(!Character.isUpperCase(name.charAt(0))) |
323 |
|
{ |
324 |
|
return name; |
325 |
|
} |
326 |
|
else |
327 |
|
{ |
328 |
|
try |
329 |
|
{ |
330 |
|
if(Character.isUpperCase(name.charAt(1))) |
331 |
|
{ |
332 |
|
return name; |
333 |
|
} |
334 |
|
else |
335 |
|
{ |
336 |
|
char[] c = name.toCharArray(); |
337 |
|
c[0] = Character.toLowerCase(c[0]); |
338 |
|
return new String(c); |
339 |
|
} |
340 |
|
} |
341 |
|
catch(StringIndexOutOfBoundsException E) |
342 |
|
{ |
343 |
|
char[] c = new char[1]; |
344 |
|
c[0] = Character.toLowerCase(name.charAt(0)); |
345 |
|
return new String(c); |
346 |
|
} |
347 |
} |
} |
348 |
|
} |
349 |
|
catch(StringIndexOutOfBoundsException E) |
350 |
|
{ |
351 |
|
return name; |
352 |
|
} |
353 |
|
catch(NullPointerException E) |
354 |
|
{ |
355 |
|
return null; |
356 |
|
} |
357 |
|
} |
358 |
|
|
359 |
|
static BeanInfo copyBeanInfo(BeanInfo b) |
360 |
|
{ |
361 |
|
java.awt.Image[] icons = new java.awt.Image[4]; |
362 |
|
for(int i=1;i<=4;i++) |
363 |
|
{ |
364 |
|
icons[i-1] = b.getIcon(i); |
365 |
|
} |
366 |
|
return new ExplicitBeanInfo(b.getBeanDescriptor(), |
367 |
|
b.getAdditionalBeanInfo(), |
368 |
|
b.getPropertyDescriptors(), |
369 |
|
b.getDefaultPropertyIndex(), |
370 |
|
b.getEventSetDescriptors(), |
371 |
|
b.getDefaultEventIndex(), |
372 |
|
b.getMethodDescriptors(),icons); |
373 |
|
} |
374 |
} |
} |
375 |
|
|
376 |
class ExplicitInfo { |
class ExplicitInfo |
377 |
BeanDescriptor explicitBeanDescriptor; |
{ |
378 |
BeanInfo[] explicitBeanInfo; |
BeanDescriptor explicitBeanDescriptor; |
379 |
|
BeanInfo[] explicitBeanInfo; |
380 |
PropertyDescriptor[] explicitPropertyDescriptors; |
|
381 |
EventSetDescriptor[] explicitEventSetDescriptors; |
PropertyDescriptor[] explicitPropertyDescriptors; |
382 |
MethodDescriptor[] explicitMethodDescriptors; |
EventSetDescriptor[] explicitEventSetDescriptors; |
383 |
|
MethodDescriptor[] explicitMethodDescriptors; |
384 |
int defaultProperty; |
|
385 |
int defaultEvent; |
int defaultProperty; |
386 |
|
int defaultEvent; |
387 |
java.awt.Image[] im = new java.awt.Image[4]; |
|
388 |
|
java.awt.Image[] im = new java.awt.Image[4]; |
389 |
Class propertyStopClass; |
|
390 |
Class eventStopClass; |
Class propertyStopClass; |
391 |
Class methodStopClass; |
Class eventStopClass; |
392 |
|
Class methodStopClass; |
393 |
ExplicitInfo(Class beanClass, Class stopClass) { |
|
394 |
while(beanClass != null && !beanClass.equals(stopClass)) { |
ExplicitInfo(Class beanClass, Class stopClass) |
395 |
BeanInfo explicit = findExplicitBeanInfo(beanClass); |
{ |
396 |
if(explicit != null) { |
while(beanClass != null && !beanClass.equals(stopClass)) |
397 |
if(explicitBeanDescriptor == null) { |
{ |
398 |
explicitBeanDescriptor = explicit.getBeanDescriptor(); |
BeanInfo explicit = findExplicitBeanInfo(beanClass); |
399 |
} |
if(explicit != null) |
400 |
if(explicitBeanInfo == null) { |
{ |
401 |
explicitBeanInfo = explicit.getAdditionalBeanInfo(); |
if(explicitBeanDescriptor == null) |
402 |
} |
{ |
403 |
if(explicitPropertyDescriptors == null) { |
explicitBeanDescriptor = explicit.getBeanDescriptor(); |
404 |
if(explicit.getPropertyDescriptors() != null) { |
} |
405 |
explicitPropertyDescriptors = explicit.getPropertyDescriptors(); |
if(explicitBeanInfo == null) |
406 |
defaultProperty = explicit.getDefaultPropertyIndex(); |
{ |
407 |
propertyStopClass = beanClass; |
explicitBeanInfo = explicit.getAdditionalBeanInfo(); |
408 |
} |
} |
409 |
} |
if(explicitPropertyDescriptors == null) |
410 |
if(explicitEventSetDescriptors == null) { |
{ |
411 |
if(explicit.getEventSetDescriptors() != null) { |
if(explicit.getPropertyDescriptors() != null) |
412 |
explicitEventSetDescriptors = explicit.getEventSetDescriptors(); |
{ |
413 |
defaultEvent = explicit.getDefaultEventIndex(); |
explicitPropertyDescriptors = explicit.getPropertyDescriptors(); |
414 |
eventStopClass = beanClass; |
defaultProperty = explicit.getDefaultPropertyIndex(); |
415 |
} |
propertyStopClass = beanClass; |
416 |
} |
} |
417 |
if(explicitMethodDescriptors == null) { |
} |
418 |
if(explicit.getMethodDescriptors() != null) { |
if(explicitEventSetDescriptors == null) |
419 |
explicitMethodDescriptors = explicit.getMethodDescriptors(); |
{ |
420 |
methodStopClass = beanClass; |
if(explicit.getEventSetDescriptors() != null) |
421 |
} |
{ |
422 |
} |
explicitEventSetDescriptors = explicit.getEventSetDescriptors(); |
423 |
if(im[0] == null |
defaultEvent = explicit.getDefaultEventIndex(); |
424 |
&& im[1] == null |
eventStopClass = beanClass; |
425 |
&& im[2] == null |
} |
426 |
&& im[3] == null) { |
} |
427 |
im[0] = explicit.getIcon(0); |
if(explicitMethodDescriptors == null) |
428 |
im[1] = explicit.getIcon(1); |
{ |
429 |
im[2] = explicit.getIcon(2); |
if(explicit.getMethodDescriptors() != null) |
430 |
im[3] = explicit.getIcon(3); |
{ |
431 |
} |
explicitMethodDescriptors = explicit.getMethodDescriptors(); |
432 |
} |
methodStopClass = beanClass; |
433 |
beanClass = beanClass.getSuperclass(); |
} |
434 |
} |
} |
435 |
if(propertyStopClass == null) { |
if(im[0] == null && im[1] == null |
436 |
propertyStopClass = stopClass; |
&& im[2] == null && im[3] == null) |
437 |
} |
{ |
438 |
if(eventStopClass == null) { |
im[0] = explicit.getIcon(0); |
439 |
eventStopClass = stopClass; |
im[1] = explicit.getIcon(1); |
440 |
} |
im[2] = explicit.getIcon(2); |
441 |
if(methodStopClass == null) { |
im[3] = explicit.getIcon(3); |
442 |
methodStopClass = stopClass; |
} |
443 |
} |
} |
444 |
} |
beanClass = beanClass.getSuperclass(); |
445 |
|
} |
446 |
static Hashtable explicitBeanInfos = new Hashtable(); |
if(propertyStopClass == null) |
447 |
static Vector emptyBeanInfos = new Vector(); |
{ |
448 |
|
propertyStopClass = stopClass; |
449 |
static BeanInfo findExplicitBeanInfo(Class beanClass) { |
} |
450 |
BeanInfo retval = (BeanInfo)explicitBeanInfos.get(beanClass); |
if(eventStopClass == null) |
451 |
if(retval != null) { |
{ |
452 |
return retval; |
eventStopClass = stopClass; |
453 |
} else if(emptyBeanInfos.indexOf(beanClass) != -1) { |
} |
454 |
return null; |
if(methodStopClass == null) |
455 |
} else { |
{ |
456 |
retval = reallyFindExplicitBeanInfo(beanClass); |
methodStopClass = stopClass; |
457 |
if(retval != null) { |
} |
458 |
explicitBeanInfos.put(beanClass,retval); |
} |
459 |
} else { |
|
460 |
emptyBeanInfos.addElement(beanClass); |
static Hashtable explicitBeanInfos = new Hashtable(); |
461 |
} |
static Vector emptyBeanInfos = new Vector(); |
462 |
return retval; |
|
463 |
} |
static BeanInfo findExplicitBeanInfo(Class beanClass) |
464 |
|
{ |
465 |
|
BeanInfo retval = (BeanInfo)explicitBeanInfos.get(beanClass); |
466 |
|
if(retval != null) |
467 |
|
{ |
468 |
|
return retval; |
469 |
|
} |
470 |
|
else if(emptyBeanInfos.indexOf(beanClass) != -1) |
471 |
|
{ |
472 |
|
return null; |
473 |
|
} |
474 |
|
else |
475 |
|
{ |
476 |
|
retval = reallyFindExplicitBeanInfo(beanClass); |
477 |
|
if(retval != null) |
478 |
|
{ |
479 |
|
explicitBeanInfos.put(beanClass,retval); |
480 |
|
} |
481 |
|
else |
482 |
|
{ |
483 |
|
emptyBeanInfos.addElement(beanClass); |
484 |
|
} |
485 |
|
return retval; |
486 |
|
} |
487 |
|
} |
488 |
|
|
489 |
|
static BeanInfo reallyFindExplicitBeanInfo(Class beanClass) |
490 |
|
{ |
491 |
|
try |
492 |
|
{ |
493 |
|
try |
494 |
|
{ |
495 |
|
return (BeanInfo)Class.forName(beanClass.getName()+"BeanInfo").newInstance(); |
496 |
|
} |
497 |
|
catch(ClassNotFoundException E) |
498 |
|
{ |
499 |
} |
} |
500 |
|
String newName = ClassHelper.getTruncatedClassName(beanClass) + "BeanInfo"; |
501 |
static BeanInfo reallyFindExplicitBeanInfo(Class beanClass) { |
for(int i=0;i<Introspector.beanInfoSearchPath.length;i++) |
502 |
try { |
{ |
503 |
try { |
try |
504 |
return (BeanInfo)Class.forName(beanClass.getName()+"BeanInfo").newInstance(); |
{ |
505 |
} catch(ClassNotFoundException E) { |
if(Introspector.beanInfoSearchPath[i].equals("")) |
506 |
} |
{ |
507 |
String newName = ClassHelper.getTruncatedClassName(beanClass) + "BeanInfo"; |
return (BeanInfo)Class.forName(newName).newInstance(); |
508 |
for(int i=0;i<Introspector.beanInfoSearchPath.length;i++) { |
} |
509 |
try { |
else |
510 |
if(Introspector.beanInfoSearchPath[i].equals("")) { |
{ |
511 |
return (BeanInfo)Class.forName(newName).newInstance(); |
return (BeanInfo)Class.forName(Introspector.beanInfoSearchPath[i] + "." + newName).newInstance(); |
512 |
} else { |
} |
513 |
return (BeanInfo)Class.forName(Introspector.beanInfoSearchPath[i] + "." + newName).newInstance(); |
} |
514 |
} |
catch(ClassNotFoundException E) |
515 |
} catch(ClassNotFoundException E) { |
{ |
516 |
} |
} |
|
} |
|
|
} catch(IllegalAccessException E) { |
|
|
} catch(InstantiationException E) { |
|
|
} |
|
|
return null; |
|
517 |
} |
} |
518 |
|
} |
519 |
|
catch(IllegalAccessException E) |
520 |
|
{ |
521 |
|
} |
522 |
|
catch(InstantiationException E) |
523 |
|
{ |
524 |
|
} |
525 |
|
return null; |
526 |
|
} |
527 |
} |
} |