KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > kernel > SystemFactory


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2003 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64 package com.jcorporate.expresso.kernel;
65
66 import com.jcorporate.expresso.kernel.digester.ComponentConfig;
67 import com.jcorporate.expresso.kernel.digester.ExpressoServicesConfig;
68 import com.jcorporate.expresso.kernel.exception.ConfigurationException;
69 import com.jcorporate.expresso.kernel.management.ComponentFactory;
70 import com.jcorporate.expresso.kernel.management.ExpressoRuntimeMap;
71 import org.apache.log4j.Logger;
72
73 import java.net.MalformedURLException JavaDoc;
74 import java.net.URL JavaDoc;
75 import java.util.ArrayList JavaDoc;
76 import java.util.Iterator JavaDoc;
77 import java.util.List JavaDoc;
78
79
80 /**
81  * <p/>
82  * This class is the focalpoint class that constructs the Expresso Runtime
83  * system. It loads the Expresso Services files, Metadata files and
84  * constructs everything as needed.
85  * </p>
86  * <p>Typical Usage for loading the expresso services configuration from
87  * the classpath: <br/>
88  * <code><pre>
89  * globalContainer = SystemFactory.buildExpressoComponentSystem(
90  * this.getClass().getResource("Test1ExpressoServices.xml"),
91  * this.getClass().getResource("TestLog4jConfig.xml"),
92  * "/My/Log/Location");
93  * </pre></code>
94  * </P
95  *
96  * @author Michael Rimov
97  */

98 public class SystemFactory {
99     /**
100      * Default filename to look for in classloader if all else fails.
101      */

102     public static final String JavaDoc DEFAULT_EXPRESSO_SERVICES = "expresso-services.xml";
103
104     /**
105      * The order that components were initialized
106      */

107     private List JavaDoc componentOrder = new ArrayList JavaDoc(10);
108
109     /**
110      * The order that components were configured. configOrder(x) ==
111      * configuration for componentOrder(x)
112      */

113     private List JavaDoc configOrder = new ArrayList JavaDoc(10);
114
115     /**
116      * Default constructor.... should not be accessed directly.
117      */

118     protected SystemFactory() {
119     }
120
121     /**
122      * Factory Method.
123      *
124      * @return an instantiated SystemFactory object
125      */

126     public static SystemFactory getInstance() {
127         return new SystemFactory();
128     }
129
130     /**
131      * Basic initialization system.
132      *
133      * @param servicesFile The path location of the services file. If null,
134      * the system will attempt to use the ClassLoader to locate an
135      * expresso-services file.
136      * @param loggingConfiguration The location of the logging configuration
137      * file. If null, the system will be initialized via a log4j.xml
138      * file in the classpath.
139      * @param logDir the location where Expresso wants to use as a logging
140      * directory.
141      * @return an instantiated Root container.
142      */

143     public static RootContainerInterface buildExpressoComponentSystem(String JavaDoc servicesFile,
144                                                                       String JavaDoc loggingConfiguration,
145                                                                       String JavaDoc logDir)
146             throws ConfigurationException {
147         return SystemFactory.getInstance().initialize(servicesFile,
148                 loggingConfiguration, logDir);
149     }
150
151     /**
152      * Classloader compatable version of the factory system.
153      *
154      * @param servicesFile A URL to the services file. (Might be from a
155      * Class.loadResource() call.
156      * @param loggingConfiguration A URL to the logging configuration file
157      * (Might also be from a Class.loadResource() file
158      * @param logDir the path location of the log files (optional)
159      * @return A built RootContainer implementation.
160      */

161     public static RootContainerInterface buildExpressoComponentSystem(URL JavaDoc servicesFile,
162                                                                       URL JavaDoc loggingConfiguration,
163                                                                       String JavaDoc logDir)
164             throws ConfigurationException {
165         if (servicesFile == null) {
166             throw new IllegalArgumentException JavaDoc("Must have a non-null servicesFile parameter");
167         }
168
169         if (loggingConfiguration == null) {
170             throw new IllegalArgumentException JavaDoc("Must have a non-null loggingConfiguration parameter");
171         }
172
173         return SystemFactory.getInstance().initialize(servicesFile,
174                 loggingConfiguration, logDir);
175     }
176
177     /**
178      * Goes through and initializes the individual Expresso Components
179      *
180      * @param root the Root container to populate
181      * @param esc the services config file that contains what components should
182      * be initialized into the
183      */

184     public void buildAndInitializeComponents(RootContainerInterface root,
185                                              ExpressoServicesConfig esc) throws ConfigurationException {
186         long startTime = System.currentTimeMillis();
187
188         Logger initLog = Logger.getLogger(RootContainer.class);
189
190         if (initLog.isInfoEnabled()) {
191             initLog.info("Logging Initialized. Loading Expresso Services Config");
192         }
193
194         esc.loadExpressoServices();
195
196         //
197
//Register the runtime map so management tools can cross runtime
198
//boundaries.
199
//
200
ExpressoRuntimeMap.registerRuntime(esc.getName(), root);
201
202         try {
203             ComponentConfig configuration = esc.getRootConfig();
204
205             if (initLog.isDebugEnabled()) {
206                 initLog.debug("Successfully parsed expresso-services.xml");
207             }
208
209             componentOrder.add(root);
210             configOrder.add(esc.getRootConfig());
211             initializeOneContainer(root.getContainerImplementation(),
212                     configuration, initLog);
213
214             if (initLog.isInfoEnabled()) {
215                 initLog.info("Successfully loaded all component classes");
216             }
217
218             configureComponents(initLog);
219             startComponents(initLog);
220             root.setExpressoServicesConfig(esc);
221
222             long stopTime = System.currentTimeMillis();
223
224             if (initLog.isInfoEnabled()) {
225                 initLog.info("Total time for this runtime initialization: " +
226                         (stopTime - startTime) + " ms");
227             }
228         } catch (ConfigurationException ex) {
229             initLog.error("Error initializing Configuration System", ex);
230             ExpressoRuntimeMap.unregisterRuntime(esc.getName());
231             throw new ConfigurationException(ex);
232         }
233     }
234
235     /**
236      * Single location that constructs all the Container Implementation
237      * classes. This can be extended here to allow for loading of other
238      * 'pluggable' implementations at a later time
239      *
240      * @return a ComponentContainer implementation.
241      */

242     public ComponentContainer constructComponentContainer() {
243         return new DefaultContainerImpl();
244     }
245
246     /**
247      * Internal usage of the initialization system. It is synchronized so
248      * there is only one runtime parsed and added to a particular Virtual
249      * Machine at a time [should help solve any weird initialization race
250      * conditions and we aren't quite so worried about startup time]
251      *
252      * @param servicesFile A URL to the services file. (Might be from a
253      * Class.loadResource() call.
254      * @param loggingConfiguration A URL to the logging configuration file
255      * (Might also be from a Class.loadResource() file
256      * @param logDir the path location of the log files (optional)
257      * @return A built RootContainer implementation.
258      */

259     protected synchronized RootContainerInterface initialize(URL JavaDoc servicesFile,
260                                                              URL JavaDoc loggingConfiguration, String JavaDoc logDir) throws ConfigurationException {
261         LogManager lm = new LogManager(loggingConfiguration, logDir);
262         Logger initLog = Logger.getLogger(SystemFactory.class);
263
264         if (initLog.isInfoEnabled()) {
265             initLog.info("Logging Initialized. Loading Expresso Services Config");
266         }
267
268         ComponentFactory cf = ComponentFactory.getInstance();
269
270         RootContainerInterface gc = cf.constructRootContainer();
271         gc.setLogManager(lm);
272
273         ExpressoServicesConfig esc = new ExpressoServicesConfig();
274         esc.setExpressoServicesFile(servicesFile);
275         gc.setServicesFileLocation(servicesFile);
276
277         buildAndInitializeComponents(gc, esc);
278
279         return gc;
280     }
281
282     /**
283      * Protected initialization.
284      *
285      * @param servicesFile The path location of the services file. If null,
286      * the system will attempt to use the ClassLoader to locate an
287      * expresso-services file.
288      * @param loggingConfiguration The location of the logging configuration
289      * file. If null, the system will be initialized via a log4j.xml
290      * file in the classpath.
291      * @param logDir the location where Expresso wants to use as a logging
292      * directory.
293      * @return an instantiated RootContainerInterface instance
294      * @throws ConfigurationException upon configuration startup error
295      */

296     protected synchronized RootContainerInterface initialize(String JavaDoc servicesFile,
297                                                              String JavaDoc loggingConfiguration,
298                                                              String JavaDoc logDir)
299             throws ConfigurationException {
300         //
301
//Only allow one System to be built at a time.
302
//
303
synchronized (SystemFactory.class) {
304             //
305
//Initialize Logging
306
//
307
LogManager lm = new LogManager(loggingConfiguration, logDir);
308
309             Logger initLog = Logger.getLogger(SystemFactory.class);
310
311             if (initLog.isInfoEnabled()) {
312                 initLog.info("Logging Initialized. Loading Expresso Services Config");
313             }
314
315             ComponentFactory cf = ComponentFactory.getInstance();
316
317             RootContainerInterface rootContainer = cf.constructRootContainer();
318             rootContainer.setLogManager(lm);
319
320             ExpressoServicesConfig esc = new ExpressoServicesConfig();
321
322             if (servicesFile == null) {
323                 if (initLog.isDebugEnabled()) {
324                     initLog.debug("Attempting to load expresso services from class loader");
325                 }
326
327                 URL JavaDoc url = Thread.currentThread().getContextClassLoader()
328                         .getResource(DEFAULT_EXPRESSO_SERVICES);
329                 esc.setExpressoServicesFile(url);
330                 rootContainer.setServicesFileLocation(url);
331             } else {
332                 if (initLog.isDebugEnabled()) {
333                     initLog.debug("Attempting to load expresso services from file name: " +
334                             servicesFile);
335                 }
336
337                 esc.setExpressoServicesFile(servicesFile);
338
339                 java.io.File JavaDoc f = new java.io.File JavaDoc(servicesFile);
340
341                 if (f == null) {
342                     throw new ConfigurationException("Unable to get services file location as a URL.");
343                 }
344
345                 try {
346                     rootContainer.setServicesFileLocation(f.toURL());
347                 } catch (MalformedURLException JavaDoc ex) {
348                     throw new ConfigurationException("Error getting services file location as a URL.",
349                             ex);
350                 }
351             }
352
353             buildAndInitializeComponents(rootContainer, esc);
354
355             return rootContainer;
356         }
357     }
358
359     /**
360      * Configures all the initialized components that implement Configuration
361      * lifecycle events.
362      *
363      * @param log the logging system to use for informational use.
364      */

365     private void configureComponents(Logger log) {
366         ComponentFactory cf = ComponentFactory.getInstance();
367
368         for (Iterator JavaDoc i = componentOrder.iterator(), eachConfig = configOrder.iterator();
369              i.hasNext();) {
370             Object JavaDoc o = i.next();
371             ComponentConfig oneConfig = (ComponentConfig) eachConfig.next();
372
373             try {
374                 if (o instanceof ComponentLifecycle) {
375                     if (log.isDebugEnabled()) {
376                         log.debug("Configuring component: " +
377                                 o.getClass().getName());
378                     }
379
380                     ExpressoComponent ec = (ExpressoComponent) o;
381                     cf.configureComponent(oneConfig, ec);
382                 } else {
383                     if (log.isDebugEnabled()) {
384                         log.debug("Object " + o.getClass().getName() +
385                                 " does not implement ComponentLifecycle. Skipping 'configure' method");
386                     }
387                 }
388             } catch (ConfigurationException ex) {
389                 log.error("Error configuring component: " +
390                         o.getClass().getName(), ex);
391             }
392         }
393     }
394
395     /**
396      * Recursive function... initializes one container.
397      *
398      * @param currentContainer the container to initialize
399      * @param containerComponentConfig the current component configuration bean
400      * in the heirarchy.
401      * @param log the logger to log progress
402      * @throws ConfigurationException upon initialization error.
403      */

404     private void initializeOneContainer(ComponentContainer currentContainer,
405                                         ComponentConfig containerComponentConfig, Logger log)
406             throws ConfigurationException {
407         List JavaDoc children = containerComponentConfig.getChildComponents();
408
409         try {
410             ComponentFactory cf = ComponentFactory.getInstance();
411
412             for (Iterator JavaDoc i = children.iterator(); i.hasNext();) {
413                 ComponentConfig childComponentConfig = (ComponentConfig) i.next();
414                 ExpressoComponent oneObj = cf.constructComponent(currentContainer,
415                         childComponentConfig);
416
417                 this.componentOrder.add(oneObj);
418                 this.configOrder.add(childComponentConfig);
419
420                 if (log.isInfoEnabled()) {
421                     log.info("Loading component: " +
422                             childComponentConfig.getClassName() + " as " +
423                             childComponentConfig.getName());
424                 }
425
426                 ExpressoComponent ec = (ExpressoComponent) oneObj;
427
428                 if (oneObj instanceof Containable) {
429                     ComponentContainer newContainer = ((Containable) ec).getContainerImplementation();
430
431                     if (childComponentConfig.getChildComponents().size() > 0) {
432                         initializeOneContainer(newContainer,
433                                 childComponentConfig, log);
434                     }
435                 }
436             }
437         } catch (Exception JavaDoc e) {
438             log.error("Error configuring component.", e);
439         }
440     }
441
442     /**
443      * Start any components that are loaded and configured and implement the
444      * Startable interface
445      *
446      * @param log The logger to log any information that might be of note.
447      */

448     private void startComponents(Logger log) {
449         ComponentFactory cf = ComponentFactory.getInstance();
450
451         for (Iterator JavaDoc i = componentOrder.iterator(); i.hasNext();) {
452             Object JavaDoc o = i.next();
453             cf.startComponent((ExpressoComponent) o);
454         }
455     }
456 }
457
Popular Tags