1 package org.apache.turbine.services;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.ArrayList;
24 import java.util.Enumeration;
25 import java.util.Hashtable;
26 import java.util.Iterator;
27 import java.util.LinkedHashMap;
28 import java.util.LinkedHashSet;
29 import java.util.Map;
30 import java.util.Set;
31
32 import org.apache.commons.configuration.Configuration;
33 import org.apache.commons.lang.StringUtils;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public abstract class BaseServiceBroker implements ServiceBroker
60 {
61
62
63
64 private final Map<String, Class<?>> mapping = new LinkedHashMap<String, Class<?>>();
65
66
67
68
69 private final Hashtable<String, Service> services = new Hashtable<String, Service>();
70
71
72
73
74
75
76 private Configuration configuration;
77
78
79
80
81
82 public static final String SERVICE_PREFIX = "services.";
83
84
85
86
87
88 public static final String CLASSNAME_SUFFIX = ".classname";
89
90
91
92
93
94
95
96
97
98
99
100
101 private final Hashtable<String, Object> serviceObjects = new Hashtable<String, Object>();
102
103
104 private static Log log = LogFactory.getLog(BaseServiceBroker.class);
105
106
107
108
109
110 private String applicationRoot;
111
112
113
114
115 private final Hashtable<String, Service> serviceProviderInstanceMap = new Hashtable<String, Service>();
116
117
118
119
120
121
122 protected BaseServiceBroker()
123 {
124
125 }
126
127
128
129
130
131
132
133
134
135 public void setConfiguration(Configuration configuration)
136 {
137 this.configuration = configuration;
138 }
139
140
141
142
143
144
145 public Configuration getConfiguration()
146 {
147 return configuration;
148 }
149
150
151
152
153
154 public void init() throws InitializationException
155 {
156
157
158
159
160
161
162
163
164
165
166 initMapping();
167
168
169
170 initServices(false);
171 }
172
173
174
175
176
177
178
179
180
181 public void setServiceObject(String name, Object value)
182 {
183 serviceObjects.put(name, value);
184 }
185
186
187
188
189
190
191
192 public Object getServiceObject(String name)
193 {
194 return serviceObjects.get(name);
195 }
196
197
198
199
200
201
202
203
204
205 private boolean checkForInterface(Class<?> checkIfc, Class<?>[] interfaces)
206 {
207 for (Class<?> ifc : interfaces)
208 {
209 if (ifc == checkIfc)
210 {
211 return true;
212 }
213
214 Class<?>[] subInterfaces = ifc.getInterfaces();
215 if (checkForInterface(checkIfc, subInterfaces))
216 {
217 return true;
218 }
219 }
220
221 return false;
222 }
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 protected void initMapping() throws InitializationException
242 {
243
244
245 Map<String, String> earlyInitFlags = new LinkedHashMap<String, String>();
246
247
248
249
250
251
252 for (Iterator<String> keys = configuration.getKeys(); keys.hasNext();)
253 {
254 String key = keys.next();
255 String[] keyParts = StringUtils.split(key, ".");
256
257 if ((keyParts.length == 3)
258 && (keyParts[0] + ".").equals(SERVICE_PREFIX)
259 && ("." + keyParts[2]).equals(CLASSNAME_SUFFIX))
260 {
261 String serviceKey = keyParts[1];
262 log.info("Added Mapping for Service: " + serviceKey);
263
264 if (!mapping.containsKey(serviceKey))
265 {
266 String className = configuration.getString(key);
267 try
268 {
269 Class<?> clazz = Class.forName(className);
270 mapping.put(serviceKey, clazz);
271
272
273 if (checkForInterface(TurbineServiceProvider.class, clazz.getInterfaces()))
274 {
275 log.info("Found a TurbineServiceProvider: " + serviceKey + " - initializing it early");
276 earlyInitFlags.put(SERVICE_PREFIX + serviceKey + ".earlyInit", "true");
277 }
278 }
279
280 catch (ThreadDeath t)
281 {
282 throw t;
283 }
284 catch (OutOfMemoryError t)
285 {
286 throw t;
287 }
288 catch (ClassNotFoundException e)
289 {
290 throw new InitializationException("Class " + className +
291 " is unavailable. Check your jars and classes.", e);
292 }
293 catch (NoClassDefFoundError e)
294 {
295 throw new InitializationException("Class " + className +
296 " is unavailable. Check your jars and classes.", e);
297 }
298 }
299 }
300 }
301
302 for (Map.Entry<String, String> entry : earlyInitFlags.entrySet())
303 {
304 configuration.setProperty(entry.getKey(), entry.getValue());
305 }
306 }
307
308
309
310
311
312
313
314
315 @Override
316 public boolean isRegistered(String serviceName)
317 {
318 return (services.get(serviceName) != null);
319 }
320
321
322
323
324
325
326 public Iterator<String> getServiceNames()
327 {
328 return mapping.keySet().iterator();
329 }
330
331
332
333
334
335
336
337
338 public Iterator<String> getServiceNames(String prefix)
339 {
340 Set<String> keys = new LinkedHashSet<String>(mapping.keySet());
341 for(Iterator<String> key = keys.iterator(); key.hasNext();)
342 {
343 if (!key.next().startsWith(prefix))
344 {
345 key.remove();
346 }
347 }
348
349 return keys.iterator();
350 }
351
352
353
354
355
356
357
358
359
360
361 @Override
362 public synchronized void initService(String name)
363 throws InitializationException
364 {
365
366
367
368 Service instance = getServiceInstance(name);
369
370 if (!instance.getInit())
371 {
372
373 instance.init();
374 }
375 }
376
377
378
379
380
381
382
383 public void initServices()
384 {
385 try
386 {
387 initServices(false);
388 }
389 catch (InstantiationException notThrown)
390 {
391 log.debug("Caught non fatal exception", notThrown);
392 }
393 catch (InitializationException notThrown)
394 {
395 log.debug("Caught non fatal exception", notThrown);
396 }
397 }
398
399
400
401
402
403
404
405
406
407
408
409 public void initServices(boolean report)
410 throws InstantiationException, InitializationException
411 {
412 if (report)
413 {
414
415 for (Iterator<String> names = getServiceNames(); names.hasNext();)
416 {
417 doInitService(names.next());
418 }
419 }
420 else
421 {
422
423 for (Iterator<String> names = getServiceNames(); names.hasNext();)
424 {
425 try
426 {
427 doInitService(names.next());
428 }
429
430
431 catch (InstantiationException e)
432 {
433 log.error(e);
434 }
435 catch (InitializationException e)
436 {
437 log.error(e);
438 }
439 }
440 }
441 log.info("Finished initializing all services!");
442 }
443
444
445
446
447
448 private void doInitService(String name)
449 throws InstantiationException, InitializationException
450 {
451
452 if (getConfiguration(name).getBoolean("earlyInit", false))
453 {
454 log.info("Start Initializing service (early): " + name);
455 initService(name);
456 log.info("Finish Initializing service (early): " + name);
457 }
458 }
459
460
461
462
463
464
465
466
467
468 @Override
469 public synchronized void shutdownService(String name)
470 {
471 try
472 {
473 Service service = getServiceInstance(name);
474 if (service != null && service.getInit())
475 {
476 service.shutdown();
477
478 if (service.getInit() && service instanceof BaseService)
479 {
480
481
482 ((BaseService) service).setInit(false);
483 }
484 }
485 }
486 catch (InstantiationException e)
487 {
488
489 log.error("Shutdown of a nonexistent Service '"
490 + name + "' was requested", e);
491 }
492 }
493
494
495
496
497
498 @Override
499 public void shutdownServices()
500 {
501 log.info("Shutting down all services!");
502
503 String serviceName = null;
504
505
506
507
508
509
510
511
512 ArrayList<String> reverseServicesList = new ArrayList<String>();
513
514 for (Iterator<String> serviceNames = getServiceNames(); serviceNames.hasNext();)
515 {
516 serviceName = serviceNames.next();
517 reverseServicesList.add(0, serviceName);
518 }
519
520 for (Iterator<String> serviceNames = reverseServicesList.iterator(); serviceNames.hasNext();)
521 {
522 serviceName = serviceNames.next();
523 log.info("Shutting down service: " + serviceName);
524 shutdownService(serviceName);
525 }
526 }
527
528
529
530
531
532
533
534
535
536 @Override
537 public Object getService(String name) throws InstantiationException
538 {
539 Service service;
540
541 if (this.isLocalService(name))
542 {
543 try
544 {
545 service = getServiceInstance(name);
546 if (!service.getInit())
547 {
548 synchronized (service.getClass())
549 {
550 if (!service.getInit())
551 {
552 log.info("Start Initializing service (late): " + name);
553 service.init();
554 log.info("Finish Initializing service (late): " + name);
555 }
556 }
557 }
558 if (!service.getInit())
559 {
560
561
562
563
564 throw new InitializationException(
565 "init() failed to initialize service " + name);
566 }
567 return service;
568 }
569 catch (InitializationException e)
570 {
571 throw new InstantiationException("Service " + name +
572 " failed to initialize", e);
573 }
574 }
575 else if (this.isNonLocalService(name))
576 {
577 return this.getNonLocalService(name);
578 }
579 else
580 {
581 throw new InstantiationException(
582 "ServiceBroker: unknown service " + name
583 + " requested");
584 }
585 }
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604 protected Service getServiceInstance(String name)
605 throws InstantiationException
606 {
607 Service service = services.get(name);
608
609 if (service == null)
610 {
611 if (!this.isLocalService(name))
612 {
613 throw new InstantiationException(
614 "ServiceBroker: unknown service " + name
615 + " requested");
616 }
617
618 try
619 {
620 Class<?> clazz = mapping.get(name);
621
622 try
623 {
624 service = (Service) clazz.newInstance();
625
626
627
628 if (service instanceof TurbineServiceProvider)
629 {
630 this.serviceProviderInstanceMap.put(name,service);
631 }
632 }
633
634 catch (ClassCastException e)
635 {
636 throw new InstantiationException("Class " + clazz +
637 " doesn't implement the Service interface", e);
638 }
639 catch (ThreadDeath t)
640 {
641 throw t;
642 }
643 catch (OutOfMemoryError t)
644 {
645 throw t;
646 }
647 catch (Throwable t)
648 {
649 throw new InstantiationException("Failed to instantiate " + clazz, t);
650 }
651 }
652 catch (InstantiationException e)
653 {
654 throw new InstantiationException(
655 "Failed to instantiate service " + name, e);
656 }
657 service.setServiceBroker(this);
658 service.setName(name);
659 services.put(name, service);
660 }
661
662 return service;
663 }
664
665
666
667
668
669
670
671 @Override
672 public Configuration getConfiguration(String name)
673 {
674 return configuration.subset(SERVICE_PREFIX + name);
675 }
676
677
678
679
680
681
682 public void setApplicationRoot(String applicationRoot)
683 {
684 this.applicationRoot = applicationRoot;
685 }
686
687
688
689
690
691
692
693 public String getApplicationRoot()
694 {
695 return applicationRoot;
696 }
697
698
699
700
701
702
703
704
705 protected boolean isLocalService(String name)
706 {
707 return this.mapping.containsKey(name);
708 }
709
710
711
712
713
714
715
716
717
718
719 protected boolean isNonLocalService(String name)
720 {
721 String serviceName = null;
722 TurbineServiceProvider turbineServiceProvider = null;
723 Enumeration<String> list = this.serviceProviderInstanceMap.keys();
724
725 while (list.hasMoreElements())
726 {
727 serviceName = list.nextElement();
728 turbineServiceProvider = (TurbineServiceProvider) this.getService(serviceName);
729
730 if (turbineServiceProvider.exists(name))
731 {
732 return true;
733 }
734 }
735
736 return false;
737 }
738
739
740
741
742
743
744
745
746 protected Object getNonLocalService(String name)
747 throws InstantiationException
748 {
749 String serviceName = null;
750 TurbineServiceProvider turbineServiceProvider = null;
751 Enumeration<String> list = this.serviceProviderInstanceMap.keys();
752
753 while (list.hasMoreElements())
754 {
755 serviceName = list.nextElement();
756 turbineServiceProvider = (TurbineServiceProvider) this.getService(serviceName);
757
758 if (turbineServiceProvider.exists(name))
759 {
760 return turbineServiceProvider.get(name);
761 }
762 }
763
764 throw new InstantiationException(
765 "ServiceBroker: unknown non-local service " + name
766 + " requested");
767 }
768 }