1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57:
58:
70:
71: public class IntrospectionIncubator {
72: Hashtable propertyMethods = new Hashtable();
73: Hashtable listenerMethods = new Hashtable();
74: Vector otherMethods = new Vector();
75:
76: Class propertyStopClass;
77: Class eventStopClass;
78: Class methodStopClass;
79:
80: public IntrospectionIncubator() {
81: }
82:
83:
101: public void addMethod(Method method) {
102: if(Modifier.isPublic(method.getModifiers())) {
103: String name = ClassHelper.getTruncatedName(method.getName());
104: Class retType = method.getReturnType();
105: Class[] params = method.getParameterTypes();
106: boolean isVoid = retType.equals(java.lang.Void.TYPE);
107: Class methodClass = method.getDeclaringClass();
108:
109:
113: if(isReachable(propertyStopClass, methodClass)) {
114:
118: if(Modifier.isStatic(method.getModifiers())) {
119:
120: otherMethods.addElement(method);
121: } else if(name.startsWith("is")
122: && retType.equals(java.lang.Boolean.TYPE)
123: && params.length == 0) {
124:
125: addToPropertyHash(name,method,IS);
126: } else if(name.startsWith("get") && !isVoid) {
127: if(params.length == 0) {
128:
129: addToPropertyHash(name,method,GET);
130: } else if(params.length == 1 && params[0].equals(java.lang.Integer.TYPE)) {
131:
132: addToPropertyHash(name,method,GET_I);
133: } else {
134:
135: otherMethods.addElement(method);
136: }
137: } else if(name.startsWith("set") && isVoid) {
138: if(params.length == 1) {
139:
140: addToPropertyHash(name,method,SET);
141: } else if(params.length == 2 && params[0].equals(java.lang.Integer.TYPE)) {
142:
143: addToPropertyHash(name,method,SET_I);
144: } else {
145:
146: otherMethods.addElement(method);
147: }
148: }
149: }
150:
151: if(isReachable(eventStopClass, methodClass)) {
152: if(name.startsWith("add")
153: && isVoid
154: && params.length == 1
155: && java.util.EventListener.class.isAssignableFrom(params[0])) {
156: addToListenerHash(name,method,ADD);
157: } else if(name.startsWith("remove")
158: && isVoid
159: && params.length == 1
160: && java.util.EventListener.class.isAssignableFrom(params[0])) {
161: addToListenerHash(name,method,REMOVE);
162: }
163: }
164:
165: if(isReachable(methodStopClass, methodClass)) {
166:
167: otherMethods.addElement(method);
168: }
169:
170: }
171: }
172:
173: public void addMethods(Method[] m) {
174: for(int i=0;i<m.length;i++) {
175: addMethod(m[i]);
176: }
177: }
178:
179: public void setPropertyStopClass(Class c) {
180: propertyStopClass = c;
181: }
182:
183: public void setEventStopClass(Class c) {
184: eventStopClass = c;
185: }
186:
187: public void setMethodStopClass(Class c) {
188: methodStopClass = c;
189: }
190:
191:
192: public BeanInfoEmbryo getBeanInfoEmbryo() throws IntrospectionException {
193: BeanInfoEmbryo b = new BeanInfoEmbryo();
194: findXXX(b,IS);
195: findXXXInt(b,GET_I);
196: findXXXInt(b,SET_I);
197: findXXX(b,GET);
198: findXXX(b,SET);
199: findAddRemovePairs(b);
200: for(int i=0;i<otherMethods.size();i++) {
201: MethodDescriptor newMethod = new MethodDescriptor((Method)otherMethods.elementAt(i));
202: if(!b.hasMethod(newMethod)) {
203: b.addMethod(new MethodDescriptor((Method)otherMethods.elementAt(i)));
204: }
205: }
206: return b;
207: }
208:
209: public BeanInfo getBeanInfo() throws IntrospectionException {
210: return getBeanInfoEmbryo().getBeanInfo();
211: }
212:
213:
214: void findAddRemovePairs(BeanInfoEmbryo b) throws IntrospectionException {
215: Enumeration listenerEnum = listenerMethods.keys();
216: while(listenerEnum.hasMoreElements()) {
217: DoubleKey k = (DoubleKey)listenerEnum.nextElement();
218: Method[] m = (Method[])listenerMethods.get(k);
219: if(m[ADD] != null && m[REMOVE] != null) {
220: EventSetDescriptor e = new EventSetDescriptor(Introspector.decapitalize(k.getName()),
221: k.getType(), k.getType().getMethods(),
222: m[ADD],m[REMOVE]);
223: e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class));
224: if(!b.hasEvent(e)) {
225: b.addEvent(e);
226: }
227: }
228: }
229: }
230:
231: void findXXX(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
232: Enumeration keys = propertyMethods.keys();
233: while(keys.hasMoreElements()) {
234: DoubleKey k = (DoubleKey)keys.nextElement();
235: Method[] m = (Method[])propertyMethods.get(k);
236: if(m[funcType] != null) {
237: PropertyDescriptor p = new PropertyDescriptor(Introspector.decapitalize(k.getName()),
238: m[IS] != null ? m[IS] : m[GET],
239: m[SET]);
240: if(m[SET] != null) {
241: p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class));
242: }
243: if(!b.hasProperty(p)) {
244: b.addProperty(p);
245: }
246: }
247: }
248: }
249:
250: void findXXXInt(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
251: Enumeration keys = propertyMethods.keys();
252: while(keys.hasMoreElements()) {
253: DoubleKey k = (DoubleKey)keys.nextElement();
254: Method[] m = (Method[])propertyMethods.get(k);
255: if(m[funcType] != null) {
256: boolean constrained;
257: if(m[SET_I] != null) {
258: constrained = ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class);
259: } else {
260: constrained = false;
261: }
262:
263:
264: Class arrayType = Array.newInstance(k.getType(),0).getClass();
265: DoubleKey findSetArray = new DoubleKey(arrayType,k.getName());
266: Method[] m2 = (Method[])propertyMethods.get(findSetArray);
267: IndexedPropertyDescriptor p;
268: if(m2 == null) {
269: p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
270: null,null,
271: m[GET_I],m[SET_I]);
272: } else {
273: if(constrained && m2[SET] != null) {
274: constrained = ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class);
275: }
276: p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
277: m2[GET],m2[SET],
278: m[GET_I],m[SET_I]);
279: }
280: p.setConstrained(constrained);
281: if(!b.hasProperty(p)) {
282: b.addProperty(p);
283: }
284: }
285: }
286: }
287:
288: static final int IS=0;
289: static final int GET_I=1;
290: static final int SET_I=2;
291: static final int GET=3;
292: static final int SET=4;
293:
294: static final int ADD=0;
295: static final int REMOVE=1;
296:
297: void addToPropertyHash(String name, Method method, int funcType) {
298: String newName;
299: Class type;
300:
301: switch(funcType) {
302: case IS:
303: type = java.lang.Boolean.TYPE;
304: newName = name.substring(2);
305: break;
306: case GET_I:
307: type = method.getReturnType();
308: newName = name.substring(3);
309: break;
310: case SET_I:
311: type = method.getParameterTypes()[1];
312: newName = name.substring(3);
313: break;
314: case GET:
315: type = method.getReturnType();
316: newName = name.substring(3);
317: break;
318: case SET:
319: type = method.getParameterTypes()[0];
320: newName = name.substring(3);
321: break;
322: default:
323: return;
324: }
325: newName = capitalize(newName);
326: if (newName.length() == 0)
327: return;
328:
329: DoubleKey k = new DoubleKey(type,newName);
330: Method[] methods = (Method[])propertyMethods.get(k);
331: if(methods == null) {
332: methods = new Method[5];
333: propertyMethods.put(k,methods);
334: }
335: methods[funcType] = method;
336: }
337:
338: void addToListenerHash(String name, Method method, int funcType) {
339: String newName;
340: Class type;
341:
342: switch(funcType) {
343: case ADD:
344: type = method.getParameterTypes()[0];
345: newName = name.substring(3,name.length()-8);
346: break;
347: case REMOVE:
348: type = method.getParameterTypes()[0];
349: newName = name.substring(6,name.length()-8);
350: break;
351: default:
352: return;
353: }
354: newName = capitalize(newName);
355: if (newName.length() == 0)
356: return;
357:
358: DoubleKey k = new DoubleKey(type,newName);
359: Method[] methods = (Method[])listenerMethods.get(k);
360: if(methods == null) {
361: methods = new Method[2];
362: listenerMethods.put(k,methods);
363: }
364: methods[funcType] = method;
365: }
366:
367:
372: static boolean isReachable(Class stopClass, Class declaringClass) {
373: return stopClass == null || (stopClass.isAssignableFrom(declaringClass) && !stopClass.equals(declaringClass));
374: }
375:
376:
387: static String capitalize(String name) {
388: try {
389: if(Character.isUpperCase(name.charAt(0))) {
390: return name;
391: } else {
392: char[] c = name.toCharArray();
393: c[0] = Character.toLowerCase(c[0]);
394: return new String(c);
395: }
396: } catch(StringIndexOutOfBoundsException E) {
397: return name;
398: } catch(NullPointerException E) {
399: return null;
400: }
401: }
402: }
403:
404:
412: class DoubleKey {
413: Class type;
414: String name;
415:
416: DoubleKey(Class type, String name) {
417: this.type = type;
418: this.name = name;
419: }
420:
421: Class getType() {
422: return type;
423: }
424:
425: String getName() {
426: return name;
427: }
428:
429: public boolean equals(Object o) {
430: if(o instanceof DoubleKey) {
431: DoubleKey d = (DoubleKey)o;
432: return d.type.equals(type) && d.name.equals(name);
433: } else {
434: return false;
435: }
436: }
437:
438: public int hashCode() {
439: return type.hashCode() ^ name.hashCode();
440: }
441: }