KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > core > bootstrap > BootStrapper


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.core.bootstrap;
19
20 import org.sape.carbon.core.component.ComponentKeeper;
21 import org.sape.carbon.core.component.startup.StartupService;
22 import org.sape.carbon.core.config.ConfigurationService;
23 import org.sape.carbon.core.exception.ExceptionUtility;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import java.util.Properties JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32
33 /**
34  * <p>This class is Carbon's ultimate source for the config service and
35  * <code>ComponentKeeper</code>. If they have not been loaded already,
36  * this class knows how bootstrap the system to load them.</p>
37  *
38  * <p>All public methods are synchronized such that the first thread to acquire
39  * the lock on this class will load the Carbon Core, all other concurrent
40  * threads will wait for the first to finish. The exception to this is the
41  * getState method. This method is synchronized on a different object so that
42  * threads merely interested in the system state do not need to wait for the
43  * system to load.</p>
44  *
45  * <p>This class is final because Carbon is not designed to have this class
46  * be overridden so extending it makes no sense.</p>
47  *
48  * Copyright 2002 Sapient
49  * @since carbon 1.0
50  * @author Douglas Voet, January 2002
51  * @version $Revision: 1.39 $($Author: ghinkl $ / $Date: 2003/10/16 13:46:23 $)
52  * @stereotype singleton
53  */

54 public final class BootStrapper {
55     /** @link dependency */
56     /*#Loader lnkLoader;*/
57
58     /** The handle to Apache-commons logger */
59     private Log log = LogFactory.getLog(this.getClass());
60
61     /** The ConfigurationService for the Carbon Core */
62     private ConfigurationService configurationService = null;
63
64     /** The ComponentKeeper for the Carbon Core */
65     private ComponentKeeper componentKeeper = null;
66
67     /**
68      * Attribute to hold the state of the Carbon Core (is it loaded or not).
69      */

70     private BootStrapperStateEnum state = BootStrapperStateEnum.NOT_LOADED;
71
72     /**
73      * Object used to synchronize upon when state is accessed.
74      * This will never change, so it is final.
75      */

76     private final Object JavaDoc stateLock = new Object JavaDoc();
77
78     /**
79      * The deployement properties cache for this bootstrapper
80      */

81     private final DeploymentProperties deploymentProperties;
82
83
84     /**
85      * <p>This is a singleton so we have a private constructor to prevent
86      * impropper instantiation.</p>
87      */

88     private BootStrapper() {
89         //log carbon statistics
90
Package JavaDoc pkg = BootStrapper.class.getPackage();
91
92         if (pkg != null) {
93             if (log.isInfoEnabled()) {
94                 log.info("Loading the Carbon Core, version: "
95                     + pkg.getSpecificationTitle() + " "
96                     + pkg.getSpecificationVersion() + ", Copyright "
97                     + pkg.getSpecificationVendor());
98             }
99         } else {
100             if (log.isInfoEnabled()) {
101                 log.info("Loading the Carbon Core, no package "
102                     + "information available");
103             }
104         }
105
106         this.deploymentProperties = new DeploymentProperties();
107     }
108
109     /**
110      * <p>Gets a reference to the root configuration provider for the
111      * system.</p>
112      *
113      * @return a reference to the configuration service
114      */

115     public synchronized ConfigurationService fetchConfigurationService() {
116         load();
117         return this.configurationService;
118     }
119
120     /**
121      * <p>Gets a reference to the <code>ComponentKeeper</code>
122      * for the system.</p>
123      *
124      * @return a reference to the component keeper
125      */

126     public synchronized ComponentKeeper fetchComponentKeeper() {
127         load();
128         return this.componentKeeper;
129     }
130
131     /**
132      * <p>
133      * This method is responsible for making the calls to load of the Carbon
134      * Core. It delegates to a <code>Loader</code> to get references to the
135      * configuration service and the <code>ComponentKeeper</code> for the
136      * system.
137      * </p><p>
138      * It is synchronized so it can only be run by a single thread. It also
139      * contains logic so that it will only run once.
140      * </p>
141      */

142     public synchronized void load() {
143
144         // only load if we have not loaded already, we can tell this if
145
// the configurationService is null or the
146
// componentKeeper is null
147
if (this.configurationService == null
148            || this.componentKeeper == null) {
149
150             // This is not the prefered place for this message. Ideally
151
// this should be called with the bootstrapping of the
152
// Xml config system. Currently there is no single class
153
// that is loaded once, all are loaded many times.
154
try {
155                 javax.xml.parsers.SAXParserFactory JavaDoc saxParserFactory =
156                     javax.xml.parsers.SAXParserFactory.newInstance();
157
158                 javax.xml.parsers.SAXParser JavaDoc saxParser =
159                     saxParserFactory.newSAXParser();
160
161                 if (log.isInfoEnabled()) {
162                     log.info("System default SAXParser is: "
163                         + saxParser.getClass().getName());
164                 }
165
166             } catch (Exception JavaDoc e) {
167                 // Eat it.
168
}
169
170
171             Loader loader = fetchLoader();
172             // 1) get the ConfigurationService
173
try {
174                 this.configurationService =
175                     loader.fetchConfigurationService();
176             } catch (BootStrapException bse) {
177                 System.out.println(
178                     "The carbon services framework was unable to boot.");
179                 bse.printStackTrace();
180                 throw bse;
181             }
182
183             // 2) get the ComponentKeeper
184
this.componentKeeper =
185                 loader.fetchComponentKeeper(configurationService);
186             // 3) start startup components
187
try {
188
189                 if (log.isDebugEnabled()) {
190                     log.debug("Starting up components configured in ["
191                         + STARTUP_COMPONENT_NAME + "]");
192                 }
193                 StartupService startupService = (StartupService)
194                     componentKeeper.fetchComponent(STARTUP_COMPONENT_NAME);
195                 startupService.startComponents();
196             } catch (Exception JavaDoc e) {
197                 if (log.isWarnEnabled()) {
198                     log.warn("Could not start startup components: "
199                         + ExceptionUtility.printStackTracesToString(e));
200                 }
201             }
202
203             // set state to BootStrapperStateEnum.LOADED
204
// synchronized to make sure we write the state back to main memory
205
// and that this step is not reordered by the compiler such that it
206
// appears to happen to other threads before the system is loaded
207
synchronized (this.stateLock) {
208                 this.state = BootStrapperStateEnum.LOADED;
209             }
210         }
211     }
212
213     /**
214      * <p>Gets the state of BootStrapper. This method allows you to
215      * determine whether or no the core is up an running yet.</p>
216      * <p>Note that this method is synchronized (within the method, not in
217      * the method signature) in order to return a
218      * correct result <i>always</i>. If a <i>stale</i> result is acceptable in
219      * exchange for better performance, the synchronization can be removed.</p>
220      *
221      * @return BootStrapperStateEnum.LOADED when the BootStrapper has been
222      * loaded, BootStrapperStateEnum.NOT_LOADED otherwise
223      */

224     public BootStrapperStateEnum getState() {
225         // This needs to be synchronized in order to make sure that we get
226
// the most recent copy of state from main memory
227
synchronized (this.stateLock) {
228             return this.state;
229         }
230     }
231
232     /**
233      * This method provides access to properties that are specific to this
234      * deployment of Carbon.
235      * The system properties are searched for the requested property
236      * first. If it is not found, the value is returned from a properties
237      * file name by BootStrapper.DEPLOYMENT_CONFIG_FILE_NAME
238      * and located using the <code>ClassLoader.getResource</code>
239      * method. Deployment Properties
240      * should be properties that either change based on deployment or are
241      * required before the <code>ConfigurationService</code> is loaded. Cases
242      * of properties varying based on deployment should be minimal. In this
243      * case, the <code>DeploymentService</code> should be used.
244      * <p>
245      * This method has the same semantics as
246      * java.util.Properties.getProperty(String)
247      *
248      * @see java.lang.ClassLoader#getResource(String)
249      * @see java.util.Properties#getProperty(String)
250      * @see org.sape.carbon.services.deployment.DeploymentService
251      *
252      * @param key the name of the property
253      * @return String the value of the property or null if it does not exist
254      */

255     public String JavaDoc getDeploymentProperty(String JavaDoc key) {
256         return this.deploymentProperties.get(key);
257     }
258
259     /**
260      * This method sets Deployment properties. If the property exists within
261      * the System properties, it is replaced, otherwise, it is written to the
262      * deployment properties maintained by this class. It does not write the
263      * new value to the properties file. This method affects the smallest
264      * scope possible. It will not write to the system wide properties unless
265      * the property already exists because that could affect other applications
266      * running in the same JVM.
267      * <p>
268      * This method has the same semantics as
269      * java.util.Properties.setProperty(String, String)
270      *
271      * @see java.util.Properties#setProperty(String, String)
272      *
273      * @param key the key to store the value in
274      * @param value the value of the deployment property
275      * @return Object the old value of the deployment property
276      */

277     public Object JavaDoc setDeploymentProperty(String JavaDoc key, String JavaDoc value) {
278         return this.deploymentProperties.set(key, value);
279     }
280
281     /**
282      * <p>
283      * Factory method for getting a <code>Loader</code> to load the system.
284      * This method defaults to using the <code>DefaultLoader</code> unless
285      * the system property defined by BOOT_LOADER_PROPERTY is set on the
286      * commandline. In that case, the value of the system property must refer
287      * to a class that implements <code>Loader</code>.
288      * </p>
289      *
290      * @return the proper loader to load the system
291      */

292     private Loader fetchLoader() {
293
294
295         String JavaDoc loaderClassName = this.getDeploymentProperty(
296             BOOT_LOADER_PROPERTY);
297
298         if (loaderClassName == null || "".equals(loaderClassName)) {
299             loaderClassName = DEFAULT_LOADER_CLASS_NAME;
300         }
301
302         try {
303
304             if (log.isDebugEnabled()) {
305                 log.debug("Using boot loader ["
306                     + loaderClassName + "] to bootstrap the system");
307             }
308             return (Loader) Class.forName(loaderClassName).newInstance();
309
310         } catch (ClassCastException JavaDoc cce) {
311             throw new BootStrapException(this.getClass(),
312                 "Specified loader [" + loaderClassName
313                 + "] was not of the correct type: ["
314                 + Loader.class.getName() + "]", cce);
315         } catch (ClassNotFoundException JavaDoc cnfe) {
316             throw new BootStrapException(this.getClass(),
317                 "Could not instantiate Loader: ["
318                 + loaderClassName + "]", cnfe);
319         } catch (InstantiationException JavaDoc ie) {
320             throw new BootStrapException(this.getClass(),
321                 "Could not instantiate Loader: ["
322                 + loaderClassName + "]", ie);
323         } catch (IllegalAccessException JavaDoc iae) {
324             throw new BootStrapException(this.getClass(),
325                 "Could not instantiate Loader: ["
326                 + loaderClassName + "]", iae);
327         }
328     }
329
330     /**
331      * The bootloader key definition to override the bootloader
332      */

333     public static final String JavaDoc BOOT_LOADER_PROPERTY =
334         "carbon.bootstrap.Loader";
335     /**
336      * The key to the class name of the default loader
337      */

338     private static final String JavaDoc DEFAULT_LOADER_CLASS_NAME =
339         "org.sape.carbon.core.bootstrap.DefaultLoader";
340     /**
341      * The default name of the startup component service
342      */

343     private static final String JavaDoc STARTUP_COMPONENT_NAME =
344         "/core/StartupService";
345     /**
346      * The single static reference to the boot strapper of this system.
347      */

348     private static final BootStrapper INSTANCE = new BootStrapper();
349
350     /** @link dependency */
351     /*#StartupService lnkStartupService;*/
352
353     /**
354      * <p>
355      * Static factory method for getting a reference to the
356      * <code>BootStrapper</code>.
357      * </p>
358      *
359      * @return BootStrapper
360      */

361     public static BootStrapper getInstance() {
362         return BootStrapper.INSTANCE;
363     }
364 }
365
Popular Tags