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