1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.clazz.reflect;
17
18 import java.beans.BeanInfo;
19 import java.beans.IndexedPropertyDescriptor;
20 import java.beans.Introspector;
21 import java.beans.PropertyDescriptor;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.apache.commons.clazz.Clazz;
30 import org.apache.commons.clazz.ClazzInstanceFactory;
31 import org.apache.commons.clazz.ClazzLoader;
32 import org.apache.commons.clazz.ClazzOperation;
33 import org.apache.commons.clazz.ClazzProperty;
34 import org.apache.commons.clazz.reflect.common.ReflectedListProperty;
35 import org.apache.commons.clazz.reflect.common.ReflectedScalarProperty;
36
37
38
39
40
41
42
43 public abstract class ReflectedClazz extends Clazz {
44
45 private Class instanceClass;
46 private boolean superClazzKnown;
47 private Clazz superClazz;
48
49
50
51
52 private Map propertyMap;
53 private List propertyList;
54 private List declaredPropertyList;
55
56
57
58
59 private Map operationMap;
60 private List operationList;
61 private List declaredOperationList;
62
63
64
65
66 private Map factoryMap;
67 private List factoryList;
68
69 private boolean hasLookedForBeanInfo = false;
70 private BeanInfo beanInfo;
71
72
73
74
75
76
77 public ReflectedClazz(ClazzLoader loader, Class instanceClass) {
78 super(loader, getCanonicalClassName(instanceClass));
79 this.instanceClass = instanceClass;
80 }
81
82 public Class getInstanceClass() {
83 return instanceClass;
84 }
85
86
87
88
89
90
91 protected abstract ReflectedPropertyIntrospector[]
92 getPropertyIntrospectors();
93
94
95
96
97 protected abstract ReflectedOperationIntrospector[]
98 getOperationIntrospectors();
99
100
101
102
103 protected abstract ReflectedInstanceFactoryIntrospector[]
104 getInstanceFactoryIntrospectors();
105
106
107
108
109 public boolean isLoggingEnabled() {
110 return getClazzLoader().isLoggingEnabled(getName());
111 }
112
113
114
115
116
117 public Class getReflectedClass() {
118 return instanceClass;
119 }
120
121
122
123
124 public Clazz getSuperclazz() {
125 if (!superClazzKnown) {
126 superClazzKnown = true;
127 Class superclass = instanceClass.getSuperclass();
128 if (superclass == null) {
129 superClazz = null;
130 }
131 else {
132 superClazz =
133 getClazzLoader().getClazzForName(superclass.getName());
134 }
135 }
136 return superClazz;
137 }
138
139
140
141
142
143
144
145
146
147
148 public List getDeclaredProperties() {
149 if (declaredPropertyList == null) {
150 if (instanceClass.getSuperclass() == null) {
151 declaredPropertyList = getProperties();
152 }
153 else {
154 List superProperties = getSuperclazz().getProperties();
155 if (superProperties.size() == 0) {
156 declaredPropertyList = getProperties();
157 }
158 else {
159 HashSet superNames = new HashSet();
160 for (int i = 0; i < superProperties.size(); i++) {
161 ClazzProperty property =
162 (ClazzProperty) superProperties.get(i);
163 superNames.add(property.getName());
164 }
165
166 List properties = getProperties();
167 declaredPropertyList = new ArrayList();
168 for (int i = 0; i < properties.size(); i++) {
169 ClazzProperty property =
170 (ClazzProperty) properties.get(i);
171 String name = property.getName();
172 if (!superNames.contains(name)) {
173 declaredPropertyList.add(property);
174 }
175 }
176 }
177 }
178 }
179 return declaredPropertyList;
180 }
181
182
183
184 public List getProperties() {
185 if (propertyList == null) {
186 introspectProperties();
187 if (isLoggingEnabled()) {
188 logPropertyParseResults();
189 }
190 }
191 return propertyList;
192 }
193
194
195
196 public ClazzProperty getProperty(String name) {
197 if (propertyMap == null) {
198 introspectProperties();
199 if (isLoggingEnabled()) {
200 logPropertyParseResults();
201 }
202 }
203 return (ClazzProperty) propertyMap.get(name);
204 }
205
206 protected void addProperty(ClazzProperty property) {
207 propertyMap.put(property.getName(), property);
208 if (property instanceof ReflectedProperty) {
209 String[] aliases = ((ReflectedProperty) property).getAliases();
210 for (int i = 0; i < aliases.length; i++) {
211 propertyMap.put(aliases[i], property);
212 }
213 }
214 propertyList.add(property);
215 }
216
217
218
219 public List getOperations() {
220 if (operationList == null) {
221 introspectOperations();
222
223
224
225 }
226 return operationList;
227 }
228
229
230
231
232 public List getDeclaredOperations() {
233 if (declaredOperationList == null) {
234 introspectOperations();
235
236
237
238 }
239 return declaredOperationList;
240 }
241
242
243
244
245 public ClazzOperation getOperation(String signature) {
246 if (operationMap == null) {
247 introspectOperations();
248
249
250
251 }
252 return (ClazzOperation) operationMap.get(signature);
253 }
254
255 protected void addOperation(ClazzOperation operation) {
256 operationMap.put(operation.getSignature(), operation);
257 declaredOperationList.add(operation);
258 }
259
260
261
262
263 public List getInstanceFactories() {
264 if (factoryList == null) {
265 introspectInstanceFactories();
266
267
268
269 }
270 return factoryList;
271 }
272
273
274
275
276
277
278
279
280
281 public ClazzInstanceFactory getInstanceFactory(String signature) {
282 if (factoryMap == null) {
283 introspectInstanceFactories();
284
285
286
287 }
288 if (signature == null) {
289 signature = "()";
290 }
291 return (ClazzInstanceFactory) factoryMap.get(signature);
292 }
293
294 protected void addInstanceFactory(ClazzInstanceFactory factory) {
295 factoryMap.put(factory.getSignature(), factory);
296 factoryList.add(factory);
297 }
298
299
300
301
302
303
304 public boolean isAssignableFrom(Clazz clazz) {
305 if (clazz == this) {
306 return true;
307 }
308 if (clazz instanceof ReflectedClazz) {
309 return getReflectedClass().isAssignableFrom(
310 ((ReflectedClazz) clazz).getReflectedClass());
311 }
312 return super.isAssignableFrom(clazz);
313 }
314
315
316
317
318
319 protected void introspectProperties() {
320 propertyList = new ArrayList();
321 propertyMap = new HashMap();
322
323 BeanInfo beanInfo = getBeanInfo();
324
325 if (beanInfo != null) {
326 PropertyDescriptor pds[] = beanInfo.getPropertyDescriptors();
327 if (pds != null) {
328 for (int i = 0; i < pds.length; i++) {
329 PropertyDescriptor pd = pds[i];
330 if (pd instanceof IndexedPropertyDescriptor) {
331 IndexedPropertyDescriptor ipd =
332 (IndexedPropertyDescriptor) pd;
333 ReflectedListProperty prop =
334 new ReflectedListProperty(this, ipd.getName());
335 prop.setType(ipd.getPropertyType());
336 prop.setContentType(ipd.getIndexedPropertyType());
337 prop.setReadMethod(ipd.getReadMethod());
338 prop.setWriteMethod(ipd.getWriteMethod());
339 prop.setGetMethod(ipd.getIndexedReadMethod());
340 prop.setSetMethod(ipd.getIndexedWriteMethod());
341 addProperty(prop);
342 }
343 else {
344 ReflectedScalarProperty prop =
345 new ReflectedScalarProperty(this, pd.getName());
346 prop.setType(pd.getPropertyType());
347 prop.setReadMethod(pd.getReadMethod());
348 prop.setWriteMethod(pd.getWriteMethod());
349 addProperty(prop);
350 }
351 }
352 }
353 }
354 else {
355 ReflectedPropertyIntrospector introspectors[] =
356 getPropertyIntrospectors();
357
358 if (introspectors != null) {
359 for (int i = 0; i < introspectors.length; i++) {
360 List properties =
361 introspectors[i].introspectProperties(
362 this,
363 instanceClass);
364 for (int j = 0; j < properties.size(); j++) {
365 ClazzProperty property =
366 (ClazzProperty) properties.get(j);
367 addProperty(property);
368 }
369 }
370 }
371 }
372 }
373
374
375
376
377
378 protected BeanInfo getBeanInfo() {
379 if (!hasLookedForBeanInfo) {
380 hasLookedForBeanInfo = true;
381 beanInfo = lookupBeanInfo();
382 }
383 return beanInfo;
384 }
385
386
387
388
389
390 private BeanInfo lookupBeanInfo() {
391 ClassLoader classLoader = instanceClass.getClassLoader();
392
393 String name = instanceClass.getName() + "BeanInfo";
394 try {
395 return (BeanInfo) instantiate(classLoader, name);
396 }
397 catch (Exception ex) {
398
399 }
400
401
402 try {
403 if (BeanInfo.class.isAssignableFrom(instanceClass)) {
404 return (BeanInfo) instanceClass.newInstance();
405 }
406 }
407 catch (Exception ex) {
408
409 }
410
411
412 while (name.indexOf('.') > 0) {
413 name = name.substring(name.indexOf('.') + 1);
414 }
415
416 String[] searchPath = Introspector.getBeanInfoSearchPath();
417 for (int i = 0; i < searchPath.length; i++) {
418 try {
419 String fullName = searchPath[i] + "." + name;
420 return (BeanInfo) instantiate(classLoader, fullName);
421 }
422 catch (Exception ex) {
423
424 }
425 }
426 return null;
427 }
428
429 static Object instantiate(ClassLoader classLoader, String className)
430 throws
431 InstantiationException,
432 IllegalAccessException,
433 ClassNotFoundException
434 {
435 if (classLoader != null) {
436 try {
437 Class cls = classLoader.loadClass(className);
438 return cls.newInstance();
439 }
440 catch (Exception ex) {
441
442 }
443 }
444
445
446 Class cls = Class.forName(className);
447 return cls.newInstance();
448 }
449
450
451
452
453
454 protected void introspectOperations() {
455 declaredOperationList = new ArrayList();
456 operationMap = new HashMap();
457 operationList = new ArrayList();
458
459 Clazz superClazz = getSuperclazz();
460 if (superClazz != null) {
461 List superOps = superClazz.getOperations();
462 for (int i = 0; i < superOps.size(); i++) {
463 ClazzOperation operation = (ClazzOperation) superOps.get(i);
464 operationMap.put(operation.getSignature(), operation);
465 }
466 }
467
468 ReflectedOperationIntrospector introspectors[] =
469 getOperationIntrospectors();
470
471 if (introspectors != null) {
472 for (int i = 0; i < introspectors.length; i++) {
473 List operations =
474 introspectors[i].introspectOperations(this, instanceClass);
475 for (int j = 0; j < operations.size(); j++) {
476 ClazzOperation operation =
477 (ClazzOperation) operations.get(j);
478 addOperation(operation);
479 }
480 }
481 }
482 operationList.addAll(operationMap.values());
483 }
484
485
486
487
488
489 protected void introspectInstanceFactories() {
490 factoryMap = new HashMap();
491 factoryList = new ArrayList();
492
493 ReflectedInstanceFactoryIntrospector introspectors[] =
494 getInstanceFactoryIntrospectors();
495
496 if (introspectors != null) {
497 for (int i = 0; i < introspectors.length; i++) {
498 List factories =
499 introspectors[i].introspectInstanceFactories(
500 this,
501 instanceClass);
502 for (int j = 0; j < factories.size(); j++) {
503 ClazzInstanceFactory factory =
504 (ClazzInstanceFactory) factories.get(j);
505 addInstanceFactory(factory);
506 }
507 }
508 }
509 }
510
511 private List propertyParseResults;
512
513
514
515
516
517 public void logPropertyParseResults(Object parseResults) {
518 if (propertyParseResults == null) {
519 propertyParseResults = new ArrayList();
520 }
521 propertyParseResults.add(parseResults);
522 }
523
524
525
526
527 protected void logPropertyParseResults() {
528 if (propertyParseResults == null) {
529 return;
530 }
531
532
533 Collections.sort(propertyParseResults);
534
535
536 System.err.println("[Clazz: " + getName());
537 for (int i = 0; i < propertyParseResults.size(); i++) {
538 System.err.println(propertyParseResults.get(i));
539 }
540 System.err.println("]");
541 }
542 }