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