1 package org.apache.turbine.services;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.ArrayList;
58 import java.util.Hashtable;
59 import java.util.Iterator;
60 import java.util.Properties;
61 import org.apache.commons.configuration.BaseConfiguration;
62 import org.apache.commons.configuration.Configuration;
63 import org.apache.turbine.util.StringUtils;
64
65
66 /***
67 * A generic implementation of a <code>ServiceBroker</code>.
68 *
69 * Functionality that <code>ServiceBroker</code> provides in addition
70 * to <code>InitableBroker</code> functionality includes:
71 *
72 * <ul>
73 *
74 * <li>Maintaining service name to class name mapping, allowing
75 * plugable service implementations.</li>
76 *
77 * <li>Providing <code>Services</code> with <code>Properties</code>
78 * based on system wide configuration mechanism.</li>
79 *
80 * </ul>
81 *
82 * @author <a href="mailto:burton@apache.org">Kevin Burton</a>
83 * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
84 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
85 * @version $Id: BaseServiceBroker.java,v 1.4 2002/07/11 16:53:29 mpoeschl Exp $
86 */
87 public abstract class BaseServiceBroker
88 extends BaseInitableBroker
89 implements ServiceBroker
90 {
91 /*** Mapping of Service names to class names. */
92 //protected Hashtable mapping = new Hashtable();
93 protected Configuration mapping = (Configuration) new BaseConfiguration();
94
95 /*** A repository of Service instances. */
96 protected Hashtable services = new Hashtable();
97
98 /***
99 * Default constructor of InitableBorker.
100 *
101 * This constructor does nothing.
102 */
103 protected BaseServiceBroker()
104 {
105 }
106
107 /***
108 * Determines whether a service is registered in the configured
109 * <code>TurbineResources.properties</code>.
110 *
111 * @param serviceName The name of the service whose existance to check.
112 * @return Registration predicate for the desired services.
113 */
114 public boolean isRegistered(String serviceName)
115 {
116 return (services.get(serviceName) != null);
117 }
118
119 /***
120 * Performs early initialization of specified service.
121 *
122 * @param name The name of the service (generally the
123 * <code>SERVICE_NAME</code> constant of the service's interface
124 * definition).
125 * @param data An object to use for initialization activities.
126 * @exception InitializationException Initilaization of this
127 * service was not successful.
128 */
129 public void initService( String name, Object data )
130 throws InitializationException
131 {
132 String className = mapping.getString(name);
133 if (StringUtils.isEmpty(className))
134 {
135 throw new InitializationException(
136 "ServiceBroker: initialization of unknown service " +
137 name + " requested.");
138 }
139 initClass(className, data);
140 }
141
142 /***
143 * Performs early initialization of all services. Failed early
144 * initialization of a Service may be non-fatal to the system,
145 * thuss the exceptions are logged and then discarded.
146 *
147 * @param data An Object to use for initialization activities.
148 */
149 public void initServices( Object data )
150 {
151 try
152 {
153 initServices(data, false);
154 }
155 catch(InstantiationException notThrown)
156 {
157 }
158 catch(InitializationException notThrown)
159 {
160 }
161 }
162
163 /***
164 * Performs early initiailzation of all services. You can decide
165 * to handle failed initizalizations if you wish, but then
166 * after one service fails, the other will not have the chance
167 * to initialize.
168 *
169 * @param data An Object to use for initialization activities.
170 * @param report <code>true</code> if you want exceptions thrown.
171 */
172 public void initServices( Object data, boolean report )
173 throws InstantiationException, InitializationException
174 {
175 notice("Initializing all services using: " +
176 data.getClass().getName());
177 Iterator names = mapping.getKeys();
178 // throw exceptions
179 if(report)
180 {
181 while(names.hasNext())
182 {
183 doInitService(data, (String)names.next());
184 }
185 }
186 // eat exceptions
187 else
188 {
189 while(names.hasNext())
190 {
191 try
192 {
193 doInitService(data, (String)names.next());
194 }
195 // In case of an exception, file an error message; the
196 // system may be still functional, though.
197 catch(InstantiationException e)
198 {
199 error(e);
200 }
201 catch(InitializationException e)
202 {
203 error(e);
204 }
205 }
206 }
207 notice("Finished initializing all services!");
208 }
209
210 /***
211 * Internal utility method for use in initServices()
212 * to prevent duplication of code.
213 */
214 private void doInitService(Object data, String name)
215 throws InstantiationException, InitializationException
216 {
217 notice("Start Initializing service (early): " + name);
218
219 // Make sure the service has it's name and broker
220 // reference set before initialization.
221 getServiceInstance(name);
222
223 // Perform early initialization.
224 initClass(mapping.getString(name), data);
225
226 notice("Finish Initializing service (early): " + name);
227 }
228
229 /***
230 * Shuts down a <code>Service</code>.
231 *
232 * This method is used to release resources allocated by a
233 * Service, and return it to its initial (uninitailized) state.
234 *
235 * @param name The name of the <code>Service</code> to be uninitialized.
236 */
237 public void shutdownService( String name )
238 {
239 String className = mapping.getString(name);
240 if (className != null)
241 {
242 shutdownClass(className);
243 }
244 }
245
246 /***
247 * Shuts down all Turbine services, releasing allocated resources and
248 * returning them to their initial (uninitailized) state.
249 */
250 public void shutdownServices( )
251 {
252 notice("Shutting down all services!");
253
254 Iterator serviceNames = mapping.getKeys();
255 String serviceName = null;
256
257 /*
258 * Now we want to reverse the order of
259 * this list. This functionality should be added to
260 * the ExtendedProperties in the commons but
261 * this will fix the problem for now.
262 */
263
264 ArrayList reverseServicesList = new ArrayList();
265
266 while (serviceNames.hasNext())
267 {
268 serviceName = (String)serviceNames.next();
269 reverseServicesList.add(0, serviceName);
270 }
271
272 serviceNames = reverseServicesList.iterator();
273
274 while (serviceNames.hasNext())
275 {
276 serviceName = (String)serviceNames.next();
277 notice("Shutting down service: " + serviceName);
278 shutdownService(serviceName);
279 }
280 }
281
282 /***
283 * Returns an instance of requested Service.
284 *
285 * @param name The name of the Service requested.
286 * @return An instance of requested Service.
287 * @exception InstantiationException, if the service is unknown or
288 * can't be initialized.
289 */
290 public Service getService( String name )
291 throws InstantiationException
292 {
293 Service service;
294 try
295 {
296 service = getServiceInstance(name);
297 if(!service.getInit())
298 {
299 synchronized(service.getClass())
300 {
301 if(!service.getInit())
302 {
303 notice("Start Initializing service (late): " + name);
304 service.init();
305 notice("Finish Initializing service (late): " + name);
306 }
307 }
308 }
309 if(!service.getInit())
310 {
311 // this exception will be caught & rethrown by this very method.
312 // getInit() returning false indicates some initialization issue,
313 // which in turn prevents the InitableBroker from passing a
314 // reference to a working instance of the initable to the client.
315 throw new InitializationException(
316 "init() failed to initialize service " + name);
317 }
318 return service;
319 }
320 catch( InitializationException e )
321 {
322 throw new InstantiationException("Service " + name +
323 " failed to initialize", e);
324 }
325 }
326
327 /***
328 * Retrieves an instance of a Service without triggering late
329 * initialization.
330 *
331 * Early initialization of a Service can require access to Service
332 * properties. The Service must have its name and serviceBroker
333 * set by then. Therefore, before calling
334 * Initable.initClass(Object), the class must be instantiated with
335 * InitableBroker.getInitableInstance(), and
336 * Service.setServiceBroker() and Service.setName() must be
337 * called. This calls for two - level accesing the Services
338 * instances.
339 *
340 * @param name The name of the service requested.
341 * @exception InstantiationException, if the service is unknown or
342 * can't be initialized.
343 */
344 protected Service getServiceInstance( String name )
345 throws InstantiationException
346 {
347 Service service = (Service)services.get(name);
348
349 if(service == null)
350 {
351 String className = mapping.getString(name);
352 if(className == null)
353 {
354 throw new InstantiationException(
355 "ServiceBroker: unknown service " + name + " requested");
356 }
357 try
358 {
359 service = (Service)getInitableInstance(className);
360 }
361 catch(ClassCastException e)
362 {
363 throw new InstantiationException(
364 "ServiceBroker: class " + className +
365 " does not implement Service interface.", e);
366 }
367 catch(InstantiationException e)
368 {
369 throw new InstantiationException(
370 "Failed to instantiate service " + name, e);
371 }
372 service.setServiceBroker(this);
373 service.setName(name);
374 services.put(name, service);
375 }
376
377 return service;
378 }
379
380 /***
381 * Returns the properites of a specific service.
382 *
383 * Generic ServiceBroker returns empty set of Properties.
384 *
385 * @param name The name of the service.
386 * @return Properties of requested Service.
387 */
388 public Properties getProperties( String name )
389 {
390 return new Properties();
391 }
392
393 /***
394 * Returns the Configuration of a specific service.
395 *
396 * Generic ServiceBroker returns empty Configuration
397 *
398 * @param name The name of the service.
399 * @return Properties of requested Service.
400 */
401 public Configuration getConfiguration( String name )
402 {
403 return (Configuration) new BaseConfiguration();
404 }
405 }
This page was automatically generated by Maven