KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > pluto > portalImpl > services > ServiceManager


1 /*
2  * Copyright 2003,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17
18  */

19
20 package org.apache.pluto.portalImpl.services;
21
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.LinkedList JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29
30 import javax.servlet.ServletConfig JavaDoc;
31 import javax.servlet.ServletContext JavaDoc;
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 JavaDoc SERVICES_CONFIG_FILE = "/WEB-INF/config/services.properties";
76     private final static String JavaDoc 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 JavaDoc aConfig) throws Exception JavaDoc
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 JavaDoc aConfig,
114                              String JavaDoc aServiceConfigFile,
115                              String JavaDoc aServiceConfigDir) throws Exception JavaDoc
116     {
117         // avoid duplicate initialization of services
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 JavaDoc 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 JavaDoc exc)
153         {
154             if (context != null)
155                 context.log ("ServiceManager: File \"" + aServiceConfigFile + "\" cannot be found or read.");
156             throw new Exception JavaDoc("ServiceManager: File \"" + aServiceConfigFile + "\" cannot be found or read.");
157         }
158
159         int numAll = 0;
160         int numSuccessful = 0;
161
162         for (Iterator JavaDoc iter = props.names (); iter.hasNext (); )
163         {
164             String JavaDoc serviceBaseName = (String JavaDoc) iter.next ();
165
166             numAll++;
167
168             // ty to get hold of the base service
169

170             Class JavaDoc serviceBase;
171
172             try
173             {
174                 serviceBase = Class.forName (serviceBaseName);
175             }
176             catch (ClassNotFoundException JavaDoc 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 JavaDoc serviceImplName = props.getString (serviceBaseName);
185
186             Class JavaDoc 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 JavaDoc 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 JavaDoc exc)
211                 {
212                     // ignore -- we go without properties then
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 JavaDoc 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 JavaDoc 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 JavaDoc exc)
238             {
239                 if (context != null)
240                     context.log ("ServiceManager: Service implementation " + serviceImplName + " cannot be instantiated.", exc);
241
242                 continue;
243             }
244             catch (Exception JavaDoc 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                 // build up list in reverse order for later destruction
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 JavaDoc("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 JavaDoc aConfig) {
279           // avoid duplicate destruction of services
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 JavaDoc context = null;
301
302         if (aConfig != null)
303             context = aConfig.getServletContext ();
304
305         // post init all services
306
for (Iterator JavaDoc iterator = cServicesList.iterator (); iterator.hasNext (); )
307        {
308            Service service = (Service) iterator.next ();
309
310            try
311            {
312                service.postInit(aConfig);
313            }
314            catch (Exception JavaDoc 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 JavaDoc aConfig)
331     {
332         // avoid duplicate destruction of services
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 JavaDoc context = null;
354
355         if (aConfig != null)
356             context = aConfig.getServletContext ();
357
358         // destroy the services in reverse order
359

360         for (Iterator JavaDoc iterator = cServicesList.iterator (); iterator.hasNext (); )
361         {
362             Service service = (Service) iterator.next ();
363
364             try
365             {
366                 service.destroy (aConfig);
367             }
368             catch (Exception JavaDoc 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 JavaDoc aClass)
391     {
392         // at this state the services map is read-only,
393
// therefore we can go without synchronization
394

395         return ((Service) cServicesMap.get (aClass));
396     }
397
398     // --- PRIVATE MEMBERS --- //
399

400     private static volatile boolean cInitialized = false;
401
402     private static Map JavaDoc cServicesMap = new HashMap JavaDoc ();
403     private static List JavaDoc cServicesList = new LinkedList JavaDoc ();
404 }
405
406
407
408
Popular Tags