01: package biz.hammurapi.config;
02:
03: public abstract class ServiceBase extends ComponentBase implements
04: Service {
05:
06: private String status;
07:
08: private ThreadLocal prevServiceTL = new ThreadLocal();
09:
10: ServiceBase prevService;
11: ServiceBase nextService;
12:
13: /**
14: * Services shall implement initialization sequence in this method.
15: * @throws ConfigurationException
16: */
17: protected abstract void startInternal()
18: throws ConfigurationException;
19:
20: /**
21: * This implementation can be invoked multiple times. ServiceBase class maintains internal started flag to ensure
22: * that startInternal() method is invoked only once. The naming bus invokes this method every time before returning
23: * service from get() method.
24: */
25: public final synchronized void start()
26: throws ConfigurationException {
27: if (!"Started".equals(status)) {
28: if ("Starting".equals(status)) {
29: throw new ConfigurationException(
30: "Circular dependency: start() method reentered by the same thread");
31: }
32: startInternal();
33:
34: prevService = (ServiceBase) prevServiceTL.get();
35: prevServiceTL.set(this );
36: if (prevService != null) {
37: prevService.nextService = this ;
38: }
39: }
40: }
41:
42: protected abstract void stopInternal()
43: throws ConfigurationException;
44:
45: /**
46: * Invokes stopInternal if all dependent services has been stopped.
47: * Otherwise goes into "stoppable" state. When stops, also stops all
48: * stoppable previous services.
49: */
50: public final synchronized void stop() throws ConfigurationException {
51: if (nextService == null || nextService.status == null) {
52: stopInternal();
53: status = null;
54: if (prevService != null
55: && "Stoppable".equals(prevService.status)) {
56: prevService.stop();
57: }
58: } else {
59: status = "Stoppable";
60: }
61: }
62:
63: }
|