View Javadoc

1   /*
2    * Copyright (c) 2005-2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.danube.service;
14  
15  import java.util.HashSet;
16  import java.util.Iterator;
17  import java.util.Set;
18  
19  import org.slf4j.Logger;
20  import org.slf4j.LoggerFactory;
21  
22  /**
23   * This class represents a Service that can run independently under some framework.
24   *
25   * @author Daniel Sendula
26   *
27   * @has 1 - n org.abstracthorizon.danube.service.ServiceNotificationListener
28   */
29  public abstract class Service implements Runnable {
30  
31      public static final int NOT_INITIALIZED = 0;
32      public static final int INITIALIZED = 1;
33      public static final int STARTED = 2;
34      public static final int RUNNING = 3;
35      public static final int STOPPING = 4;
36      public static final int STOPPED = 5;
37      public static final int DESTROYED = 6;
38  
39      public static final String[] SERVICE_STATE_NAMES = new String[] {
40          "NOT INSTALLED",
41          "INITIALIZED",
42          "STARTED",
43          "RUNNING",
44          "STOPPING",
45          "STOPPED",
46          "DESTROYED"
47      };
48  
49      protected final Logger logger = LoggerFactory.getLogger(getClass());
50  
51      /** Service state */
52      private int state = NOT_INITIALIZED;
53  
54      /** Flag to signal to service that it needs to stop */
55      protected boolean stopService = false;
56  
57      /** Listeners */
58      protected Set<ServiceNotificationListener> listeners;
59  
60      /** Service name */
61      protected String name;
62  
63      /** Constructor */
64      public Service() {
65      }
66  
67      /**
68       * Sets service's name
69       * @param name service's name
70       */
71      public void setName(String name) {
72          this.name = name;
73      }
74  
75      /**
76       * Returns service name
77       * @return service name
78       */
79      public String getName() {
80          return name;
81      }
82  
83      /**
84       * This method changes state. It notifies all registered listeners about the change.
85       * @param newState new state
86       */
87      protected void changeState(int newState) {
88          synchronized (this) {
89              if (listeners != null) {
90                  Iterator<ServiceNotificationListener> it = listeners.iterator();
91                  while (it.hasNext()) {
92                      ServiceNotificationListener listener = it.next();
93                      listener.serviceAboutToChangeState(this, newState);
94                  }
95              }
96              int oldState = state;
97              if (logger.isDebugEnabled()) {
98                  String name = getName();
99                  if (name != null) {
100                     logger.debug("Changed service " + getName() + " state from " + SERVICE_STATE_NAMES[oldState] + " to " + SERVICE_STATE_NAMES[newState]);
101                 } else {
102                     logger.debug("Changed unnamed service state from " + SERVICE_STATE_NAMES[oldState] + " to " + SERVICE_STATE_NAMES[newState]);
103                 }
104             }
105             state = newState;
106             if (listeners != null) {
107                 Iterator<ServiceNotificationListener> it = listeners.iterator();
108                 while (it.hasNext()) {
109                     ServiceNotificationListener listener = (ServiceNotificationListener)it.next();
110                     listener.serviceChangedState(this, oldState);
111                 }
112             }
113             state = newState;
114         }
115     }
116 
117     /**
118      * Adds new listener
119      * @param listener listener
120      */
121     public void addListener(ServiceNotificationListener listener) {
122         if (listeners == null) {
123             listeners = new HashSet<ServiceNotificationListener>();
124         }
125         listeners.add(listener);
126     }
127 
128     /**
129      * Removes a listener
130      * @param listener listener
131      */
132     public void removeListener(ServiceNotificationListener listener) {
133         listeners.remove(listener);
134     }
135 
136     /**
137      * Returns current state
138      * @return current state
139      */
140     public int getState() {
141         return state;
142     }
143 
144     /**
145      * Returns state as a string
146      * @return state as a string
147      */
148     public String getStateName() {
149         if ((state > 0) && (state < SERVICE_STATE_NAMES.length)) {
150             return SERVICE_STATE_NAMES[state];
151         } else {
152             return "UNKNOWN(" + state + ")";
153         }
154     }
155 
156     /**
157      * This method is to be called for service to be set-up.
158      * This implementation does nothing.
159      * @throws ServiceException
160      */
161     public void create() throws ServiceException {
162         changeState(INITIALIZED);
163     }
164 
165     /**
166      * This method is to be called when service is to be removed from the system.
167      * This implementation does nothing.
168      * @throws Exception
169      */
170     public void destroy() throws ServiceException {
171         changeState(DESTROYED);
172     }
173 
174     /**
175      * This method is to be called for service to be started.
176      * @throws Exception
177      */
178     public void start() throws ServiceException {
179         synchronized (this) {
180             stopService = false;
181         }
182         changeState(STARTED);
183     }
184 
185     /**
186      * This method is to be called for service to be stopped. Service won't stop
187      * immediately but only {@link #stopService} flag is going to be set to <code>true</code>
188      * @throws Exception
189      */
190     public void stop() throws ServiceException {
191         changeState(STOPPING);
192         synchronized (this) {
193             stopService = true;
194         }
195     }
196 
197 }