1 package org.apache.fulcrum.factory;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.ObjectOutputStream;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.concurrent.ConcurrentHashMap;
29
30 import org.apache.avalon.framework.activity.Disposable;
31 import org.apache.avalon.framework.activity.Initializable;
32 import org.apache.avalon.framework.configuration.Configurable;
33 import org.apache.avalon.framework.configuration.Configuration;
34 import org.apache.avalon.framework.configuration.ConfigurationException;
35 import org.apache.avalon.framework.logger.AbstractLogEnabled;
36 import org.apache.fulcrum.factory.utils.ObjectInputStreamForContext;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class DefaultFactoryService extends AbstractLogEnabled
52 implements FactoryService, Configurable, Initializable, Disposable {
53
54
55
56
57 private static final String CLASS_LOADER = "classloader";
58
59
60
61
62 private static final String OBJECT_FACTORY = "object-factory";
63
64
65
66
67 protected static final String DEFAULT_FACTORY = "default";
68
69
70
71
72 private static HashMap<String, Class<?>> primitiveClasses = new HashMap<String, Class<?>>(8);
73
74 {
75 primitiveClasses.put(Boolean.TYPE.toString(), Boolean.TYPE);
76 primitiveClasses.put(Character.TYPE.toString(), Character.TYPE);
77 primitiveClasses.put(Byte.TYPE.toString(), Byte.TYPE);
78 primitiveClasses.put(Short.TYPE.toString(), Short.TYPE);
79 primitiveClasses.put(Integer.TYPE.toString(), Integer.TYPE);
80 primitiveClasses.put(Long.TYPE.toString(), Long.TYPE);
81 primitiveClasses.put(Float.TYPE.toString(), Float.TYPE);
82 primitiveClasses.put(Double.TYPE.toString(), Double.TYPE);
83 }
84
85
86
87
88 private String[] loaderNames;
89
90
91
92 private ArrayList<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
93
94
95
96 private ConcurrentHashMap<String, Factory<?>> objectFactories = new ConcurrentHashMap<String, Factory<?>>();
97
98
99
100 private ConcurrentHashMap<String, String> objectFactoryClasses = new ConcurrentHashMap<String, String>();
101
102
103
104
105
106
107
108 protected static Class<?> getPrimitiveClass(String type)
109 {
110 return primitiveClasses.get(type);
111 }
112
113
114
115
116
117
118
119
120 @Override
121 public <T> T getInstance(String className) throws FactoryException
122 {
123 if (className == null) {
124 throw new FactoryException("Missing String className");
125 }
126 Factory<T> factory = getFactory(className);
127 if (factory == null) {
128 Class<T> clazz;
129 try {
130 clazz = loadClass(className);
131 } catch (ClassNotFoundException x) {
132 throw new FactoryException("Instantiation failed for class " + className, x);
133 }
134 return getInstance(clazz);
135 } else {
136 return factory.getInstance();
137 }
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152 @Override
153 public <T> T getInstance(String className, ClassLoader loader) throws FactoryException
154 {
155 Factory<T> factory = getFactory(className);
156 if (factory == null) {
157 if (loader != null) {
158 Class<T> clazz;
159 try {
160 clazz = loadClass(className, loader);
161 } catch (ClassNotFoundException x) {
162 throw new FactoryException("Instantiation failed for class " + className, x);
163 }
164 return getInstance(clazz);
165 } else {
166 return getInstance(className);
167 }
168 } else {
169 return factory.getInstance(loader);
170 }
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184 @Override
185 public <T> T getInstance(String className, Object[] params, String[] signature) throws FactoryException
186 {
187 Factory<T> factory = getFactory(className);
188 if (factory == null) {
189 Class<T> clazz;
190 try {
191 clazz = loadClass(className);
192 } catch (ClassNotFoundException x) {
193 throw new FactoryException("Instantiation failed for class " + className, x);
194 }
195 return getInstance(clazz, params, signature);
196 } else {
197 return factory.getInstance(params, signature);
198 }
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 @Override
220 public <T> T getInstance(String className, ClassLoader loader, Object[] params, String[] signature)
221 throws FactoryException
222 {
223 Factory<T> factory = getFactory(className);
224 if (factory == null) {
225 if (loader != null) {
226 Class<T> clazz;
227 try {
228 clazz = loadClass(className, loader);
229 } catch (ClassNotFoundException x) {
230 throw new FactoryException("Instantiation failed for class " + className, x);
231 }
232 return getInstance(clazz, params, signature);
233 } else {
234 return getInstance(className, params, signature);
235 }
236 } else {
237 return factory.getInstance(loader, params, signature);
238 }
239 }
240
241
242
243
244
245
246
247
248 @Override
249 public boolean isLoaderSupported(String className) throws FactoryException
250 {
251 Factory<?> factory = getFactory(className);
252 return factory != null ? factory.isLoaderSupported() : true;
253 }
254
255
256
257
258
259
260
261
262
263 @Override
264 public <T> T getInstance(Class<T> clazz) throws FactoryException
265 {
266 try {
267 return clazz.newInstance();
268 } catch (Exception x) {
269 throw new FactoryException("Instantiation failed for " + clazz.getName(), x);
270 }
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284
285 protected <T> T getInstance(Class<T> clazz, Object params[], String signature[])
286 throws FactoryException
287 {
288
289 try {
290 Class<?>[] sign = getSignature(clazz, params, signature);
291 return clazz.getConstructor(sign).newInstance(params);
292 } catch (Exception x) {
293 throw new FactoryException("Instantiation failed for " + clazz.getName(), x);
294 }
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308 @Override
309 public Class<?>[] getSignature(Class<?> clazz, Object params[], String signature[])
310 throws ClassNotFoundException
311 {
312 if (signature != null) {
313
314 ClassLoader tempLoader;
315 ClassLoader loader = clazz.getClassLoader();
316 Class<?>[] sign = new Class[signature.length];
317 for (int i = 0; i < signature.length; i++) {
318
319 sign[i] = getPrimitiveClass(signature[i]);
320 if (sign[i] == null) {
321
322 if (loader != null) {
323
324 sign[i] = loader.loadClass(signature[i]);
325 tempLoader = sign[i].getClassLoader();
326 if (params[i] != null && tempLoader != null
327 && !tempLoader.equals(params[i].getClass().getClassLoader())) {
328
329
330
331 params[i] = switchObjectContext(params[i], loader);
332 }
333 } else {
334
335 sign[i] = loadClass(signature[i]);
336 }
337 }
338 }
339 return sign;
340 } else {
341 return null;
342 }
343 }
344
345
346
347
348
349
350
351
352
353 protected Object switchObjectContext(Object object, ClassLoader loader)
354 {
355 ByteArrayOutputStream bout = new ByteArrayOutputStream();
356
357 try
358 {
359 ObjectOutputStream out = new ObjectOutputStream(bout);
360 out.writeObject(object);
361 out.flush();
362 }
363 catch (IOException x)
364 {
365 return object;
366 }
367
368 ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
369 ObjectInputStreamForContext in = null;
370
371 try
372 {
373 in = new ObjectInputStreamForContext(bin, loader);
374 return in.readObject();
375 }
376 catch (Exception x)
377 {
378 return object;
379 }
380 finally
381 {
382 if (in != null)
383 {
384 try
385 {
386 in.close();
387 }
388 catch (IOException e)
389 {
390
391 }
392 }
393 }
394 }
395
396
397
398
399
400
401
402
403 @SuppressWarnings("unchecked")
404 protected <T> Class<T> loadClass(String className) throws ClassNotFoundException
405 {
406 ClassLoader loader = this.getClass().getClassLoader();
407 try
408 {
409 Class<T> clazz;
410
411 if (loader != null)
412 {
413 clazz = (Class<T>) loader.loadClass(className);
414 }
415 else
416 {
417 clazz = (Class<T>) Class.forName(className);
418 }
419
420 return clazz;
421 }
422 catch (ClassNotFoundException x)
423 {
424
425 for (ClassLoader l : classLoaders)
426 {
427 try
428 {
429 return (Class<T>) l.loadClass(className);
430 }
431 catch (ClassNotFoundException xx)
432 {
433
434 }
435 }
436
437 throw x;
438 }
439 }
440
441
442
443
444
445
446
447
448
449 @SuppressWarnings("unchecked")
450 protected <T> Class<T> loadClass(String className, ClassLoader loader) throws ClassNotFoundException
451 {
452 if (loader != null)
453 {
454 return (Class<T>) loader.loadClass(className);
455 }
456 else
457 {
458 return loadClass(className);
459 }
460 }
461
462
463
464
465
466
467
468
469
470 @SuppressWarnings("unchecked")
471 protected <T> Factory<T> getFactory(String className) throws FactoryException
472 {
473 Factory<T> factory = (Factory<T>) objectFactories.get(className);
474 if (factory == null)
475 {
476
477 factory = (Factory<T>) objectFactories.get(DEFAULT_FACTORY);
478 }
479
480 if (factory == null) {
481
482
483 String factoryClass = objectFactoryClasses.get(className);
484 if (factoryClass == null)
485 {
486 factoryClass = objectFactoryClasses.get(DEFAULT_FACTORY);
487 }
488
489 if (factoryClass == null) {
490 return null;
491 }
492
493 try {
494 factory = getInstance(factoryClass);
495 factory.init(className);
496 }
497 catch (ClassCastException x)
498 {
499 throw new FactoryException("Incorrect factory " + factoryClass + " for class " + className, x);
500 }
501
502 Factory<T> _factory = (Factory<T>) objectFactories.putIfAbsent(className, factory);
503 if (_factory != null)
504 {
505
506 factory = _factory;
507 }
508 }
509
510 return factory;
511 }
512
513
514
515
516
517
518
519 @Override
520 public void configure(Configuration conf) throws ConfigurationException
521 {
522 final Configuration[] loaders = conf.getChildren(CLASS_LOADER);
523 if (loaders != null)
524 {
525 loaderNames = new String[loaders.length];
526 for (int i = 0; i < loaders.length; i++)
527 {
528 loaderNames[i] = loaders[i].getValue();
529 }
530 }
531
532 final Configuration factories = conf.getChild(OBJECT_FACTORY, false);
533 if (factories != null)
534 {
535
536
537 Configuration[] nameVal = factories.getChildren();
538 for (Configuration entry : nameVal)
539 objectFactoryClasses.put(entry.getName(), entry.getValue());
540
541 }
542 }
543
544
545
546
547
548
549
550 @Override
551 public void initialize() throws Exception
552 {
553 if (loaderNames != null)
554 {
555 for (String className : loaderNames)
556 {
557 try
558 {
559 ClassLoader loader = (ClassLoader) loadClass(className).newInstance();
560 classLoaders.add(loader);
561 }
562 catch (Exception x)
563 {
564 throw new Exception("No such class loader '" + className + "' for DefaultFactoryService", x);
565 }
566 }
567 loaderNames = null;
568 }
569 }
570
571
572
573
574 @Override
575 public void dispose()
576 {
577 objectFactories.clear();
578 objectFactoryClasses.clear();
579 classLoaders.clear();
580 }
581 }