KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > turbine > services > BaseInitableBroker


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

18
19 import java.util.Hashtable JavaDoc;
20 import java.util.Stack JavaDoc;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 /**
26  * A generic implementation of <code>InitableBroker</code>.
27  * Functionality provided by the broker includes:
28  *
29  * <ul>
30  *
31  * <li>Maintaining single instance of each <code>Initable</code> in
32  * the system.</li>
33  *
34  * <li>Early initialization of <code>Initables</code> during system
35  * startup.</li>
36  *
37  * <li>Late initialization of <code>Initables</code> before they are
38  * used.</li>
39  *
40  * <li>Providing instances of <code>Initables</code> to requesting
41  * parties.</li>
42  *
43  * <li>Maintaining dependencies between <code>Initables</code> during
44  * early initalization phases, including circular dependencies
45  * detection.</li>
46  *
47  * </ul>
48  *
49  * @author <a HREF="mailto:burton@apache.org">Kevin Burton</a>
50  * @author <a HREF="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
51  * @author <a HREF="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
52  * @version $Id: BaseInitableBroker.java,v 1.8.2.2 2004/05/20 03:05:18 seade Exp $
53  */

54 public abstract class BaseInitableBroker
55         implements InitableBroker
56 {
57     /** A repository of Initable instances. */
58     protected Hashtable JavaDoc initables = new Hashtable JavaDoc();
59
60     /**
61      * Names of classes being early-initialized are pushed onto this
62      * stack. A name appearing twice indicates a circular dependency
63      * chain.
64      */

65     protected Stack JavaDoc stack = new Stack JavaDoc();
66
67     /** Logging */
68     private Log log = LogFactory.getLog(this.getClass());
69
70     /**
71      * Default constructor of InitableBroker.
72      *
73      * This constructor does nothing. Your brokers should be
74      * singletons, therefore their constructors should be
75      * private. They should also have public YourBroker getInstance()
76      * methods.
77      */

78     protected BaseInitableBroker()
79     {
80     }
81
82     /**
83      * Performs early initialization of an Initable class.
84      *
85      * @param className The name of the class to be initialized.
86      * @param data An Object to be used for initialization activities.
87      * @exception InitializationException Initialization was not successful.
88      */

89     public void initClass(String JavaDoc className, Object JavaDoc data)
90             throws InitializationException
91     {
92         // make sure that only one thread calls this method recursively
93
synchronized (stack)
94         {
95             int pos = stack.search(className);
96             if (pos != -1)
97             {
98                 StringBuffer JavaDoc msg = new StringBuffer JavaDoc().append(className)
99                         .append(" couldn't be initialized because of circular depency chain:\n");
100                 for (int i = pos; i > 0; i--)
101                 {
102                     msg.append((String JavaDoc) stack.elementAt(stack.size() - i - 1) + "->");
103                 }
104                 msg.append(className).append('\n');
105
106                 throw new InitializationException(msg.toString());
107             }
108             try
109             {
110                 stack.push(className);
111                 Initable instance = getInitableInstance(className);
112                 if (!instance.getInit())
113                 {
114                     // this call might result in an indirect recursion
115
instance.init(data);
116                 }
117             }
118             finally
119             {
120                 // Succeeded or not, make sure the name gets off the stack.
121
stack.pop();
122             }
123         }
124     }
125
126     /**
127      * Shuts down an <code>Initable</code>.
128      *
129      * This method is used to release resources allocated by an
130      * <code>Initable</code>, and return it to its initial (uninitailized)
131      * state.
132      *
133      * @param className The name of the class to be uninitialized.
134      */

135     public void shutdownClass(String JavaDoc className)
136     {
137         try
138         {
139             Initable initable = getInitableInstance(className);
140             if (initable.getInit())
141             {
142                 initable.shutdown();
143                 ((BaseInitable) initable).setInit(false);
144             }
145         }
146         catch (InstantiationException JavaDoc e)
147         {
148             // Shutdown of a nonexistent class was requested.
149
// This does not hurt anything, so we log the error and continue.
150
log.error("Shutdown of a nonexistent class " +
151                     className + " was requested", e);
152         }
153     }
154
155     /**
156      * Provides an instance of Initable class ready to work.
157      *
158      * If the requested class couldn't be instatiated or initialized,
159      * an InstantiationException will be thrown. You needn't handle
160      * this exception in your code, since it indicates fatal
161      * misconfigurtion of the system.
162      *
163      * @param className The name of the Initable requested.
164      * @return An instance of the requested Initable.
165      * @exception InstantiationException if there was a problem
166      * during instantiation or initialization of the Initable.
167      */

168     public Initable getInitable(String JavaDoc className)
169             throws InstantiationException JavaDoc
170     {
171         Initable initable;
172         try
173         {
174             initable = getInitableInstance(className);
175             if (!initable.getInit())
176             {
177                 synchronized (initable.getClass())
178                 {
179                     if (!initable.getInit())
180                     {
181                         initable.init();
182                     }
183                     if (!initable.getInit())
184                     {
185                         // this exception will be caught & rethrown by this
186
// very method. getInit() returning false indicates
187
// some initialization issue, which in turn prevents
188
// the InitableBroker from passing a working
189
// instance of the initable to the client.
190
throw new InitializationException(
191                                 "init() failed to initialize class "
192                                 + className);
193                     }
194                 }
195             }
196             return initable;
197         }
198         catch (InitializationException e)
199         {
200             throw new InstantiationException JavaDoc("Class " + className +
201                     " failed to initialize", e);
202         }
203     }
204
205     /**
206      * Retrieves an instance of an Initable from the repository.
207      *
208      * If the requested class is not present in the repository, it is
209      * instantiated and passed a reference to the broker, saved and
210      * then returned.
211      *
212      * @param className The name of the class to be instantiated.
213      * @exception InstantiationException if the requested class can't
214      * be instantiated.
215      */

216     protected Initable getInitableInstance(String JavaDoc className)
217             throws InstantiationException JavaDoc
218     {
219         Initable initable = (Initable) initables.get(className);
220
221         if (initable == null)
222         {
223             try
224             {
225                 initable = (Initable) Class.forName(className).newInstance();
226             }
227
228                     // those two errors must be passed to the VM
229
catch (ThreadDeath JavaDoc t)
230             {
231                 throw t;
232             }
233             catch (OutOfMemoryError JavaDoc t)
234             {
235                 throw t;
236             }
237
238             catch (Throwable JavaDoc t)
239             {
240                 // Used to indicate error condition.
241
String JavaDoc msg = null;
242
243                 if (t instanceof NoClassDefFoundError JavaDoc)
244                 {
245                     msg = "A class referenced by " + className +
246                             " is unavailable. Check your jars and classes.";
247                 }
248                 else if (t instanceof ClassNotFoundException JavaDoc)
249                 {
250                     msg = "Class " + className +
251                             " is unavailable. Check your jars and classes.";
252                 }
253                 else if (t instanceof ClassCastException JavaDoc)
254                 {
255                     msg = "Class " + className +
256                             " doesn't implement Initable.";
257                 }
258                 else
259                 {
260                     msg = "Failed to instantiate " + className;
261                 }
262
263                 throw new InstantiationException JavaDoc(msg, t);
264             }
265
266             initable.setInitableBroker(this);
267             initables.put(className, initable);
268         }
269
270         return initable;
271     }
272
273 }
274
Popular Tags