1 package org.andromda.core.common;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.LinkedHashMap;
6 import java.util.Map;
7 import org.apache.commons.lang.StringUtils;
8 import org.apache.log4j.Logger;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 public class ComponentContainer
39 {
40 private static final Logger LOGGER = Logger.getLogger(ComponentContainer.class);
41
42
43
44
45 private static final String SERVICES = "META-INF/services/";
46
47
48
49
50 private final Map<Object, Object> container = new LinkedHashMap<Object, Object>();
51
52
53
54
55 private static ComponentContainer instance = null;
56
57
58
59
60
61
62 public static ComponentContainer instance()
63 {
64 if (instance == null)
65 {
66 instance = new ComponentContainer();
67 }
68 return instance;
69 }
70
71
72
73
74
75
76
77 public Object findComponent(final Object key)
78 {
79 return this.container.get(key);
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public Object newComponent(
95 String implementation,
96 final Class type)
97 {
98 Object component;
99 if (StringUtils.isBlank(implementation))
100 {
101 component = this.newDefaultComponent(type);
102 }
103 else
104 {
105 component = ClassUtils.newInstance(StringUtils.trimToEmpty(implementation));
106 }
107 return component;
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121 public Object newComponent(
122 final Class implementation,
123 final Class type)
124 {
125 Object component;
126 if (implementation == null)
127 {
128 component = this.newDefaultComponent(type);
129 }
130 else
131 {
132 component = ClassUtils.newInstance(implementation);
133 }
134 return component;
135 }
136
137
138
139
140
141
142
143
144
145 public Object newDefaultComponent(final Class type)
146 {
147 ExceptionUtils.checkNull("type", type);
148 Object component;
149 try
150 {
151 final String implementation = this.getDefaultImplementation(type);
152 if (StringUtils.isBlank(implementation))
153 {
154 throw new ComponentContainerException(
155 "Default configuration file '" + this.getComponentDefaultConfigurationPath(type) +
156 "' could not be found");
157 }
158 component = ClassUtils.loadClass(implementation).newInstance();
159 }
160 catch (final Throwable throwable)
161 {
162 throw new ComponentContainerException(throwable);
163 }
164 return component;
165 }
166
167
168
169
170
171
172
173 protected final String getComponentDefaultConfigurationPath(final Class type)
174 {
175 ExceptionUtils.checkNull("type", type);
176 return SERVICES + type.getName();
177 }
178
179
180
181
182
183
184
185
186
187
188 public Object findComponent(final Class key)
189 {
190 ExceptionUtils.checkNull("key", key);
191 return this.findComponent(null, key);
192 }
193
194
195
196
197
198
199
200
201
202 public Object findRequiredComponent(final Class key)
203 {
204 final Object component = this.findComponent(key);
205 if (component == null)
206 {
207 throw new ComponentContainerException(
208 "No implementation could be found for component '" + key.getName() +
209 "', please make sure you have a '" + this.getComponentDefaultConfigurationPath(key) +
210 "' file on your classpath");
211 }
212 return component;
213 }
214
215
216
217
218
219
220
221
222
223
224
225
226 public Object findComponent(
227 final String key,
228 final Class type)
229 {
230 ExceptionUtils.checkNull("type", type);
231 try
232 {
233 Object component = this.findComponent(key);
234 if (component == null)
235 {
236 final String typeName = type.getName();
237 component = this.findComponent(typeName);
238
239
240
241
242 if (component == null)
243 {
244 final String defaultImplementation = this.getDefaultImplementation(type);
245 if (StringUtils.isNotBlank(defaultImplementation))
246 {
247 component =
248 this.registerDefaultComponent(
249 ClassUtils.loadClass(typeName),
250 ClassUtils.loadClass(defaultImplementation));
251 }
252 else
253 {
254 LOGGER.warn(
255 "WARNING! Component's default configuration file '" +
256 getComponentDefaultConfigurationPath(type) + "' could not be found");
257 }
258 }
259 }
260 return component;
261 }
262 catch (final Throwable throwable)
263 {
264 throw new ComponentContainerException(throwable);
265 }
266 }
267
268
269
270
271
272
273
274
275
276 private String getDefaultImplementation(final Class type)
277 {
278 final String contents = ResourceUtils.getContents(this.getComponentDefaultConfigurationPath(type));
279 return StringUtils.trimToEmpty(contents);
280 }
281
282
283
284
285
286
287
288 public Collection findComponentsOfType(final Class type)
289 {
290 final Collection<Object> components = new ArrayList<Object>(this.container.values());
291 final Collection<Object> containerInstances = this.container.values();
292 for (final Object component : containerInstances)
293 {
294 if (component instanceof ComponentContainer)
295 {
296 components.addAll(((ComponentContainer) component).container.values());
297 }
298 }
299 final Collection<Object> componentsOfType = new ArrayList<Object>();
300 for (final Object component : components)
301 {
302 if (type.isInstance(component))
303 {
304 componentsOfType.add(component);
305 }
306 }
307 return componentsOfType;
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344 public Object unregisterComponent(final String key)
345 {
346 ExceptionUtils.checkEmpty("key", key);
347 if (LOGGER.isDebugEnabled())
348 {
349 LOGGER.debug("unregistering component with key --> '" + key + '\'');
350 }
351 return container.remove(key);
352 }
353
354
355
356
357
358
359
360
361
362 public Object findComponentByNamespace(
363 final String namespace,
364 final Object key)
365 {
366 ExceptionUtils.checkEmpty("namespace", namespace);
367 ExceptionUtils.checkNull("key", key);
368
369 Object component = null;
370 final ComponentContainer namespaceContainer = this.getNamespaceContainer(namespace);
371 if (namespaceContainer != null)
372 {
373 component = namespaceContainer.findComponent(key);
374 }
375 return component;
376 }
377
378
379
380
381
382
383
384
385 private ComponentContainer getNamespaceContainer(final String namespace)
386 {
387 return (ComponentContainer)this.findComponent(namespace);
388 }
389
390
391
392
393
394
395
396
397
398
399 public boolean isRegisteredByNamespace(
400 final String namespace,
401 final Object key)
402 {
403 ExceptionUtils.checkEmpty("namespace", namespace);
404 ExceptionUtils.checkNull("key", key);
405 final ComponentContainer namespaceContainer = this.getNamespaceContainer(namespace);
406 return namespaceContainer != null && namespaceContainer.isRegistered(key);
407 }
408
409
410
411
412
413
414
415
416 public boolean isRegistered(final Object key)
417 {
418 return this.findComponent(key) != null;
419 }
420
421
422
423
424
425
426
427
428
429 public void registerComponentByNamespace(
430 final String namespace,
431 final Object key,
432 final Object component)
433 {
434 ExceptionUtils.checkEmpty("namespace", namespace);
435 ExceptionUtils.checkNull("component", component);
436 if (LOGGER.isDebugEnabled())
437 {
438 LOGGER.debug("registering component '" + component + "' with key --> '" + key + '\'');
439 }
440 ComponentContainer namespaceContainer = this.getNamespaceContainer(namespace);
441 if (namespaceContainer == null)
442 {
443 namespaceContainer = new ComponentContainer();
444 this.registerComponent(namespace, namespaceContainer);
445 }
446 namespaceContainer.registerComponent(key, component);
447 }
448
449
450
451
452
453
454
455
456
457 public Object registerComponent(
458 final Object key,
459 final Object component)
460 {
461 ExceptionUtils.checkNull("component", component);
462 if (LOGGER.isDebugEnabled())
463 {
464 LOGGER.debug("registering component '" + component + "' with key --> '" + key + '\'');
465 }
466 return this.container.put(key, component);
467 }
468
469
470
471
472
473
474
475
476
477 public void registerDefaultComponent(
478 final Class componentInterface,
479 final String defaultTypeName)
480 {
481 ExceptionUtils.checkNull("componentInterface", componentInterface);
482 ExceptionUtils.checkEmpty("defaultTypeName", defaultTypeName);
483 try
484 {
485 this.registerDefaultComponent(
486 componentInterface,
487 ClassUtils.loadClass(defaultTypeName));
488 }
489 catch (final Throwable throwable)
490 {
491 throw new ComponentContainerException(throwable);
492 }
493 }
494
495
496
497
498
499
500
501
502
503 public Object registerDefaultComponent(
504 final Class componentInterface,
505 final Class defaultType)
506 {
507 ExceptionUtils.checkNull("componentInterface", componentInterface);
508 ExceptionUtils.checkNull("defaultType", defaultType);
509 if (LOGGER.isDebugEnabled())
510 {
511 LOGGER.debug(
512 "registering default for component '" + componentInterface + "' as type --> '" + defaultType + '\'');
513 }
514 try
515 {
516 final String interfaceName = componentInterface.getName();
517
518
519
520 if (this.isRegistered(interfaceName))
521 {
522 this.unregisterComponent(interfaceName);
523 }
524 final Object component = defaultType.newInstance();
525 this.container.put(interfaceName, component);
526 return component;
527 }
528 catch (final Throwable throwable)
529 {
530 throw new ComponentContainerException(throwable);
531 }
532 }
533
534
535
536
537
538
539 public void registerComponentType(final Class type)
540 {
541 ExceptionUtils.checkNull("type", type);
542 try
543 {
544 this.container.put(
545 type,
546 type.newInstance());
547 }
548 catch (final Throwable throwable)
549 {
550 throw new ComponentContainerException(throwable);
551 }
552 }
553
554
555
556
557
558
559
560
561 public Object registerComponentType(final String type)
562 {
563 ExceptionUtils.checkNull("type", type);
564 try
565 {
566 return this.registerComponent(
567 type,
568 ClassUtils.loadClass(type).newInstance());
569 }
570 catch (final Throwable throwable)
571 {
572 throw new ComponentContainerException(throwable);
573 }
574 }
575
576
577
578
579 public void shutdown()
580 {
581 this.container.clear();
582 ComponentContainer.instance = null;
583 }
584 }