1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.clazz;
17
18 import java.lang.ref.WeakReference;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.commons.clazz.common.ClazzElementSupport;
26 import org.apache.commons.clazz.common.ExtendedClazzLoaderFactory;
27 import org.apache.commons.clazz.common.StandardClazzLoaderFactory;
28
29
30
31
32
33
34
35
36 public abstract class Clazz extends ClazzElementSupport
37 implements ClazzElement
38 {
39 private ClazzLoader loader;
40 private String name;
41 private List listeners;
42
43
44
45
46
47 public static final String STANDARD_CLAZZ_MODEL =
48 StandardClazzLoaderFactory.MODEL;
49
50
51
52
53
54 public static final String EXTENDED_CLAZZ_MODEL =
55 ExtendedClazzLoaderFactory.MODEL;
56
57 private static String defaultClazzModel = EXTENDED_CLAZZ_MODEL;
58 private static ClazzLoader defaultClazzLoader;
59 private static Map clazzLoaderFactories = new HashMap();
60
61 static {
62 addClazzLoaderFactory(StandardClazzLoaderFactory.FACTORY);
63 addClazzLoaderFactory(ExtendedClazzLoaderFactory.FACTORY);
64 }
65
66
67
68
69
70
71
72 public static void addClazzLoaderFactory(ClazzLoaderFactory factory) {
73 clazzLoaderFactories.put(factory.getClazzModel(), factory);
74 }
75
76
77
78
79
80
81
82
83
84 public static ClazzLoaderFactory getClazzLoaderFactory(String model) {
85 return (ClazzLoaderFactory) clazzLoaderFactories.get(model);
86 }
87
88
89
90
91
92
93 public static void setDefaultClazzModel(String defaultClazzModel) {
94 Clazz.defaultClazzModel = defaultClazzModel;
95 }
96
97
98
99
100 public static String getDefaultClazzModel() {
101 return defaultClazzModel;
102 }
103
104
105
106
107
108
109
110
111
112 public static ClazzLoader getClazzLoader(
113 String model,
114 ClassLoader classLoader)
115 {
116 if (classLoader == null) {
117 classLoader = Clazz.class.getClassLoader();
118 }
119 return getClazzLoaderFactory(model).getClazzLoader(classLoader);
120 }
121
122
123
124
125 public static ClazzLoader getDefaultClazzLoader(ClassLoader classLoader) {
126 return getClazzLoader(getDefaultClazzModel(), classLoader);
127 }
128
129
130
131
132
133 public static Clazz getClazz(Object instance, String model) {
134 if (instance == null) {
135 throw new NullPointerException();
136 }
137
138 ClassLoader classLoader = instance.getClass().getClassLoader();
139 Clazz clazz = getClazzLoader(model, classLoader).getClazz(instance);
140 if (clazz == null) {
141 throw new ClazzNotFoundException(instance.getClass().getName());
142 }
143 return clazz;
144 }
145
146
147
148
149
150 public static Clazz getClazz(Object instance) {
151 return getClazz(instance, getDefaultClazzModel());
152 }
153
154
155
156
157
158
159
160
161 protected Clazz(ClazzLoader modelClazzLoader, String name) {
162 this.loader = modelClazzLoader;
163 this.name = name;
164 }
165
166
167
168
169
170 public ClazzLoader getClazzLoader() {
171 return loader;
172 }
173
174
175
176
177
178 public String getName() {
179 return name;
180 }
181
182
183
184
185
186
187 public String getPackageName() {
188 if (name == null) {
189 return null;
190 }
191 int index = name.lastIndexOf('.');
192 if (index == -1) {
193 return "";
194 }
195
196 return name.substring(0, index);
197 }
198
199
200
201
202
203
204 public String getShortClassName() {
205 if (name == null) {
206 return null;
207 }
208 int index = name.lastIndexOf('.');
209 if (index == -1) {
210 return name;
211 }
212
213 return name.substring(index + 1);
214 }
215
216
217
218
219
220 public abstract Class getInstanceClass();
221
222
223
224
225 public abstract Clazz getSuperclazz();
226
227
228
229
230
231 public boolean isAssignableFrom(Clazz clazz) {
232 if (clazz == this) {
233 return true;
234 }
235 Clazz superclazz = clazz.getSuperclazz();
236 if (superclazz != null) {
237 return isAssignableFrom(superclazz);
238 }
239 return false;
240 }
241
242
243
244
245 public abstract List getDeclaredProperties();
246
247
248
249
250
251 public abstract List getProperties();
252
253
254
255
256
257
258
259
260
261 public abstract ClazzProperty getProperty(String name);
262
263
264
265
266 public abstract List getOperations();
267
268
269
270
271 public abstract List getDeclaredOperations();
272
273
274
275
276
277
278
279
280
281
282 public abstract ClazzOperation getOperation(String signature);
283
284
285
286
287 public abstract List getInstanceFactories();
288
289
290
291
292
293
294
295
296
297
298
299 public abstract ClazzInstanceFactory getInstanceFactory(String signature);
300
301
302
303
304
305 public Object newInstance() {
306 ClazzInstanceFactory factory = getInstanceFactory("()");
307 if (factory == null) {
308
309 throw new RuntimeException(
310 "No such instance factory " + getName() + " ()");
311 }
312 return factory.newInstance(null);
313 }
314
315
316
317
318
319 public Object newInstance(String signature, Object[] parameters) {
320 ClazzInstanceFactory factory = getInstanceFactory(signature);
321 if (factory == null) {
322
323 throw new RuntimeException(
324 "No such instance factory "
325 + getName()
326 + (signature == null ? "" : " " + signature));
327 }
328 return factory.newInstance(parameters);
329 }
330
331
332
333
334 public void addClazzChangeListener(ClazzChangeListener listener) {
335 if (listeners == null) {
336 listeners = new ArrayList();
337 }
338
339
340
341 WeakReference reference = new WeakReference(listener);
342 listeners.add(reference);
343 }
344
345 public void removeClazzChangeListener(ClazzChangeListener listener) {
346 if (listeners == null) {
347 return;
348 }
349 for (Iterator iter = listeners.iterator(); iter.hasNext();) {
350 WeakReference reference = (WeakReference) iter.next();
351 if (reference.get() == listener) {
352 iter.remove();
353 break;
354 }
355 }
356 }
357
358 private static final WeakReference[] CLAZZ_CHANGE_LISTENER_ARRAY =
359 new WeakReference[0];
360
361 private abstract static class Notifier {
362 void fire(Clazz clazz, Object parameter) {
363 if (clazz.listeners != null && clazz.listeners.size() != 0) {
364 WeakReference listenerArray[] =
365 (WeakReference[]) clazz.listeners.toArray(
366 CLAZZ_CHANGE_LISTENER_ARRAY);
367 for (int i = 0; i < listenerArray.length; i++) {
368 fire(
369 clazz,
370 (ClazzChangeListener) listenerArray[i].get(),
371 parameter);
372 }
373 }
374 }
375
376 abstract void fire(
377 Clazz clazz, ClazzChangeListener listener, Object parameter);
378 }
379
380 private static final Notifier PROPERTY_ADDED_NOTIFIER = new Notifier() {
381 void fire(Clazz clazz, ClazzChangeListener listener, Object parameter) {
382 listener.propertyAdded(clazz, (ClazzProperty) parameter);
383 }
384 };
385
386 protected void firePropertyAdded(ClazzProperty property) {
387 PROPERTY_ADDED_NOTIFIER.fire(this, property);
388 }
389
390 private static final Notifier PROPERTY_REMOVED_NOTIFIER = new Notifier() {
391 void fire(Clazz clazz, ClazzChangeListener listener, Object parameter) {
392 listener.propertyRemoved(clazz, (ClazzProperty) parameter);
393 }
394 };
395
396 protected void firePropertyRemoved(ClazzProperty property) {
397 PROPERTY_REMOVED_NOTIFIER.fire(this, property);
398 }
399
400 private static final Notifier OPERATION_ADDED_NOTIFIER = new Notifier() {
401 void fire(Clazz clazz, ClazzChangeListener listener, Object parameter) {
402 listener.operationAdded(clazz, (ClazzOperation) parameter);
403 }
404 };
405
406 protected void fireOperationAdded(ClazzOperation operation) {
407 OPERATION_ADDED_NOTIFIER.fire(this, operation);
408 }
409
410 private static final Notifier OPERATION_REMOVED_NOTIFIER = new Notifier() {
411 void fire(Clazz clazz, ClazzChangeListener listener, Object parameter) {
412 listener.operationRemoved(clazz, (ClazzOperation) parameter);
413 }
414 };
415
416 protected void fireOperationRemoved(ClazzOperation operation) {
417 OPERATION_REMOVED_NOTIFIER.fire(this, operation);
418 }
419
420
421 private static final Notifier FACTORY_ADDED_NOTIFIER = new Notifier() {
422 void fire(Clazz clazz, ClazzChangeListener listener, Object parameter) {
423 listener.instanceFactoryAdded(
424 clazz,
425 (ClazzInstanceFactory) parameter);
426 }
427 };
428
429 protected void fireInstanceFactoryAdded(ClazzInstanceFactory factory) {
430 FACTORY_ADDED_NOTIFIER.fire(this, factory);
431 }
432
433 private static final Notifier FACTORY_REMOVED_NOTIFIER = new Notifier() {
434 void fire(Clazz clazz, ClazzChangeListener listener, Object parameter) {
435 listener.instanceFactoryRemoved(
436 clazz,
437 (ClazzInstanceFactory) parameter);
438 }
439 };
440
441 protected void fireInstanceFactoryRemoved(ClazzInstanceFactory factory) {
442 FACTORY_REMOVED_NOTIFIER.fire(this, factory);
443 }
444
445
446
447
448
449
450
451
452 public static String constructSignature(String name, Class[] arguments) {
453 StringBuffer buffer = new StringBuffer();
454 if (name != null) {
455 buffer.append(name);
456 }
457 buffer.append('(');
458 if (arguments != null) {
459 for (int i = 0; i < arguments.length; i++) {
460 if (i != 0) {
461 buffer.append(',');
462 }
463 buffer.append(getCanonicalClassName(arguments[i]));
464 }
465 }
466 buffer.append(')');
467 return buffer.toString();
468 }
469
470
471
472
473
474 public static String constructSignature(String name, Clazz[] arguments) {
475 StringBuffer buffer = new StringBuffer();
476 if (name != null) {
477 buffer.append(name);
478 }
479 buffer.append('(');
480 if (arguments != null) {
481 for (int i = 0; i < arguments.length; i++) {
482 if (i != 0) {
483 buffer.append(',');
484 }
485 buffer.append(arguments[i].getName());
486 }
487 }
488 buffer.append(')');
489 return buffer.toString();
490 }
491
492
493
494
495
496 public static String getCanonicalClassName(Class javaClass) {
497
498
499
500
501
502 if (javaClass.isArray()) {
503 return getCanonicalClassName(javaClass.getComponentType()) + "[]";
504 }
505 return javaClass.getName();
506 }
507 }