1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.pluto.portalImpl.services;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.Map;
29
30 import javax.servlet.ServletConfig;
31 import javax.servlet.ServletContext;
32
33 import org.apache.pluto.portalImpl.util.Properties;
34 import org.apache.pluto.util.StringUtils;
35
36 /***
37 * Manages the life-time of services registered during servlet startup.
38 * A service has to derive from {@link org.apache.pluto.services.ContainerService} and implement the
39 * <CODE>init()</CODE> and <CODE>destroy()</CODE> methods as appropriate.
40 *
41 * <P>
42 * By registering the service and its implementation in the file
43 * <CODE>/config/services.properties</CODE>, the service will become
44 * available to the portal engine. The format of the file is simple:
45 *
46 * <PRE>
47 * org.apache.pluto.portalImpl.services.log.Logger = org.apache.pluto.portalImpl.services.log.LogServicesImpl
48 * </PRE>
49 *
50 * Each entry represents one service. The left-hand side is the abstract
51 * service class, the right-hand side is the implementation of this service.
52 * The services are initialized in the order of appearance.
53 *
54 * <P>
55 * Each service can have its own configuration file, located in
56 * <CODE>/config/services</CODE>. It has to have the name of either
57 * implementation or abstract class of the service, without the
58 * leading package name. For example, the service manager looks
59 * for <CODE>LoggerImpl
60 .properties</CODE>. This allows a special
61 * implementation to provide different configuration than the
62 * general (abstract) service requires.
63 *
64 * <P>
65 * If present, one of the services configuration files is loaded
66 * and passed to the service as {@link org.apache.pluto.portalImpl.util.Properties}
67 * object. Not providing a service configuration file is okay too,
68 * in that case the properties are empty.
69 *
70 * @see org.apache.pluto.services.ContainerService
71 */
72 public class ServiceManager
73 {
74
75 private final static String SERVICES_CONFIG_FILE = "/WEB-INF/config/services.properties";
76 private final static String SERVICES_CONFIG_DIR = "/WEB-INF/config/services/";
77
78 /***
79 ** Initializes all services specified in <CODE>services.properties</CODE>.
80 ** By specifying a different implementation of the service the behaviour
81 ** of the portal can be modified.
82 **
83 ** @param aConfig
84 ** the servlet configuration
85 **
86 ** @exception Exception
87 ** if loading <CODE>services.properties</CODE>
88 ** or initializing any of its contained services fails
89 **/
90
91 public static void init (ServletConfig aConfig) throws Exception
92 {
93 init (aConfig, SERVICES_CONFIG_FILE, SERVICES_CONFIG_DIR);
94 }
95
96 /***
97 ** Initializes all services specified in <CODE>services.properties</CODE>.
98 ** By specifying a different implementation of the service the behaviour
99 ** of the portal can be modified.
100 **
101 ** @param aConfig
102 ** the servlet configuration
103 ** @param aServiceConfigFile
104 ** The location of <CODE>services.properties</CODE> (relative to classpath)
105 ** @param aServiceConfigDir
106 ** The direcory with the services' properties files (relative to classpath)
107 **
108 ** @exception Exception
109 ** if loading <CODE>services.properties</CODE>
110 ** or initializing any of its contained services fails
111 **/
112
113 public static void init (ServletConfig aConfig,
114 String aServiceConfigFile,
115 String aServiceConfigDir) throws Exception
116 {
117
118
119 if (! cInitialized)
120 {
121 synchronized (ServiceManager.class)
122 {
123 if (! cInitialized)
124 {
125 cInitialized = true;
126 }
127 else
128 {
129 return;
130 }
131 }
132 }
133 else
134 {
135 return;
136 }
137
138 ServletContext context = null;
139
140 if (aConfig != null)
141 context = aConfig.getServletContext ();
142
143 if (context != null)
144 context.log ("ServiceManager: Loading services...");
145
146 Properties props = new Properties ();
147
148 try
149 {
150 props.load (context.getResourceAsStream (aServiceConfigFile));
151 }
152 catch (IOException exc)
153 {
154 if (context != null)
155 context.log ("ServiceManager: File \"" + aServiceConfigFile + "\" cannot be found or read.");
156 throw new Exception("ServiceManager: File \"" + aServiceConfigFile + "\" cannot be found or read.");
157 }
158
159 int numAll = 0;
160 int numSuccessful = 0;
161
162 for (Iterator iter = props.names (); iter.hasNext (); )
163 {
164 String serviceBaseName = (String) iter.next ();
165
166 numAll++;
167
168
169
170 Class serviceBase;
171
172 try
173 {
174 serviceBase = Class.forName (serviceBaseName);
175 }
176 catch (ClassNotFoundException exc)
177 {
178 if (context != null)
179 context.log ("ServiceManager: A service with name " + serviceBaseName + " cannot be found.");
180
181 continue;
182 }
183
184 String serviceImplName = props.getString (serviceBaseName);
185
186 Class serviceImpl = null;
187
188 Service service = null;
189
190 try
191 {
192 serviceImpl = Class.forName (serviceImplName);
193
194 service = (Service) serviceImpl.newInstance ();
195
196 Properties serviceProps = new Properties ();
197
198 try
199 {
200 InputStream is = null;
201
202 is = context.getResourceAsStream (aServiceConfigDir + StringUtils.nameOf (serviceImpl) + ".properties");
203
204 if (is == null)
205 is = context.getResourceAsStream (aServiceConfigDir + StringUtils.nameOf (serviceBase) + ".properties");
206
207 if (is != null)
208 serviceProps.load (is);
209 }
210 catch (IOException exc)
211 {
212
213 }
214
215 if (context != null)
216 context.log (StringUtils.nameOf (serviceBase) + " initializing...");
217
218 service.init (aConfig, serviceProps);
219
220 if (context != null)
221 context.log (StringUtils.nameOf (serviceBase) + " done.");
222 }
223 catch (ClassNotFoundException exc)
224 {
225 if (context != null)
226 context.log ("ServiceManager: A service implementation with name " + serviceImplName + " cannot be found.", exc);
227
228 continue;
229 }
230 catch (ClassCastException exc)
231 {
232 if (context != null)
233 context.log ("ServiceManager: Service implementation " + serviceImplName + " is not a service of the required type.", exc);
234
235 continue;
236 }
237 catch (InstantiationException exc)
238 {
239 if (context != null)
240 context.log ("ServiceManager: Service implementation " + serviceImplName + " cannot be instantiated.", exc);
241
242 continue;
243 }
244 catch (Exception exc)
245 {
246 if (context != null)
247 context.log ("ServiceManager: An unidentified error occurred", exc);
248
249 service = null;
250 }
251
252 if (service != null)
253 {
254 cServicesMap.put (serviceBase, service);
255
256
257
258 cServicesList.add (0, service);
259
260 numSuccessful++;
261 }
262 }
263
264 if (context != null)
265 context.log ("ServiceManager: Services initialized (" + numSuccessful + "/" + numAll + " successful).");
266 if (numSuccessful!=numAll)
267 {
268 throw new Exception("ServiceManager: Services initialized (" + numSuccessful + "/" + numAll + " successful).");
269 }
270 }
271
272 /***
273 * Calls post init for all services
274 *
275 * @param aConfig
276 * the servlet configuration
277 **/
278 public static void postInit(ServletConfig aConfig) {
279
280
281 if (cInitialized)
282 {
283 synchronized (ServiceManager.class)
284 {
285 if (cInitialized)
286 {
287 cInitialized = false;
288 }
289 else
290 {
291 return;
292 }
293 }
294 }
295 else
296 {
297 return;
298 }
299
300 ServletContext context = null;
301
302 if (aConfig != null)
303 context = aConfig.getServletContext ();
304
305
306 for (Iterator iterator = cServicesList.iterator (); iterator.hasNext (); )
307 {
308 Service service = (Service) iterator.next ();
309
310 try
311 {
312 service.postInit(aConfig);
313 }
314 catch (Exception exc)
315 {
316 if (context != null)
317 context.log ("ServiceManager: Service couldn't be started (postInit) after init..", exc);
318 }
319 }
320
321 }
322
323 /***
324 ** Destroys all services.
325 **
326 ** @param aConfig
327 ** the servlet configuration
328 **/
329
330 public static void destroy (ServletConfig aConfig)
331 {
332
333
334 if (cInitialized)
335 {
336 synchronized (ServiceManager.class)
337 {
338 if (cInitialized)
339 {
340 cInitialized = false;
341 }
342 else
343 {
344 return;
345 }
346 }
347 }
348 else
349 {
350 return;
351 }
352
353 ServletContext context = null;
354
355 if (aConfig != null)
356 context = aConfig.getServletContext ();
357
358
359
360 for (Iterator iterator = cServicesList.iterator (); iterator.hasNext (); )
361 {
362 Service service = (Service) iterator.next ();
363
364 try
365 {
366 service.destroy (aConfig);
367 }
368 catch (Exception exc)
369 {
370 if (context != null)
371 context.log ("ServiceManager: Service couldn't be destroyed.", exc);
372 }
373 }
374
375 cServicesList.clear();
376 cServicesMap.clear();
377
378 }
379
380 /***
381 ** Returns the service implementation for the given service class, or
382 ** <CODE>null</CODE> if no such service is registered.
383 **
384 ** @param aClass
385 ** the service class
386 **
387 ** @return the service implementation
388 **/
389
390 public static Service getService (Class aClass)
391 {
392
393
394
395 return ((Service) cServicesMap.get (aClass));
396 }
397
398
399
400 private static volatile boolean cInitialized = false;
401
402 private static Map cServicesMap = new HashMap ();
403 private static List cServicesList = new LinkedList ();
404 }
405
406
407