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