KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > component > servlet > ExcaliburComponentManagerServlet


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

17 package org.apache.avalon.excalibur.component.servlet;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21
22 import javax.servlet.GenericServlet JavaDoc;
23 import javax.servlet.ServletConfig JavaDoc;
24 import javax.servlet.ServletContext JavaDoc;
25 import javax.servlet.ServletException JavaDoc;
26 import javax.servlet.ServletRequest JavaDoc;
27 import javax.servlet.ServletResponse JavaDoc;
28 import javax.servlet.UnavailableException JavaDoc;
29
30 import org.apache.avalon.excalibur.component.ExcaliburComponentManagerCreator;
31 import org.apache.avalon.excalibur.logger.LoggerManager;
32 import org.apache.avalon.framework.component.ComponentManager;
33 import org.apache.avalon.framework.container.ContainerUtil;
34 import org.apache.avalon.framework.service.ServiceManager;
35 import org.apache.excalibur.instrument.InstrumentManager;
36
37 /**
38  * Makes it possible for servlets to work with Avalon components
39  * without having to do any coding to setup and manage the
40  * lifecycle of the ServiceManager (ComponentManager).
41  * <p>
42  * To make use of the ExcaliburComponentManagerServet. You will
43  * need to define the servlet in your web.xml file as follows:
44  * <pre>
45  * &lt;!-- ExcaliburComponentManagerServlet (for initializing ComponentManager). --&gt;
46  * &lt;servlet&gt;
47  * &lt;servlet-name&gt;ExcaliburComponentManagerServlet&lt;/servlet-name&gt;
48  * &lt;display-name&gt;ExcaliburComponentManagerServlet&lt;/display-name&gt;
49  * &lt;description&gt;Creates component manager, does not service requests.&lt;/description&gt;
50  * &lt;servlet-class&gt;
51  * org.apache.avalon.excalibur.component.servlet.ExcaliburComponentManagerServlet
52  * &lt;/servlet-class&gt;
53  *
54  * &lt;!-- This parameter points to the logkit configuration file. --&gt;
55  * &lt;!-- Note that the path is specified in absolute notation but it will be --&gt;
56  * &lt;!-- resolved relative to the servlets webapp context path --&gt;
57  * &lt;init-param&gt;
58  * &lt;param-name&gt;logkit&lt;/param-name&gt;
59  * &lt;param-value&gt;/WEB-INF/logkit.xml&lt;/param-value&gt;
60  * &lt;/init-param&gt;
61  *
62  * &lt;!-- This parameter points to the components configuration file. --&gt;
63  * &lt;init-param&gt;
64  * &lt;param-name&gt;components&lt;/param-name&gt;
65  * &lt;param-value&gt;/WEB-INF/components.xml&lt;/param-value&gt;
66  * &lt;/init-param&gt;
67  *
68  * &lt;!-- Roles file supplements configuration file to make the latter --&gt;
69  * &lt;!-- more readable. Most likely you don't want to change the roles --&gt;
70  * &lt;!-- file --&gt;
71  * &lt;init-param&gt;
72  * &lt;param-name&gt;roles&lt;/param-name&gt;
73  * &lt;param-value&gt;/WEB-INF/roles.xml&lt;/param-value&gt;
74  * &lt;/init-param&gt;
75  *
76  * &lt;!-- This parameter points to the instrument manager configuration file. --&gt;
77  * &lt;init-param&gt;
78  * &lt;param-name&gt;instrument&lt;/param-name&gt;
79  * &lt;param-value&gt;/WEB-INF/instrument.xml&lt;/param-value&gt;
80  * &lt;/init-param&gt;
81  *
82  * &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
83  * &lt;/servlet&gt;
84  * </pre>
85  * Please pay particular attention to the load-on-startup element. It is used
86  * to control the order in which servlets are started by the servlet engine.
87  * It must have a value which is less than any other servlets making use of
88  * the ServiceManager. This is to ensure that the ServiceManager is
89  * initialized before any other servlets attempt to start using it.
90  * <p>
91  * All of the configuration files are located in the WEB-INF directory by
92  * default. The instrument configuration file is optional. Please see the
93  * {@link org.apache.avalon.excalibur.component.ExcaliburComponentManagerCreator}
94  * class for details on what goes into these configuration files. Note that
95  * the lifecycle of the ExcaliburComponentManagerCreator is managed automatically
96  * by this servlet, so there is no need to access the class directly.
97  * <p>
98  * Once the servlet has been configured, other servlets may gain access to
99  * the ServiceManager (ComponentManager), InstrumentManager and LoggerManager
100  * via the ServletContext using the following code within a servlet:
101  * <pre>
102  * // Get a reference to the ServletContext
103  * ServletContext servletContext = getServletContext();
104  *
105  * // Acquire the LoggerManager
106  * LoggerManager loggerManager =
107  * (LoggerManager)m_servletContext.getAttribute( LoggerManager.class.getName() );
108  *
109  * // Acquire the InstrumentManager
110  * InstrumentManager instrumentManager =
111  * (InstrumentManager)m_servletContext.getAttribute( InstrumentManager.class.getName() );
112  *
113  * // Acquire the ServiceManager
114  * ServiceManager serviceManager =
115  * (ServiceManager)m_servletContext.getAttribute( ServiceManager.class.getName() );
116  *
117  * // Acquire the ComponentManager ( Deprecated )
118  * ComponentManager componentManager =
119  * (ComponentManager)m_servletContext.getAttribute( ComponentManager.class.getName() );
120  * </pre>
121  * The ExcaliburComponentManagerServlet makes use of a proxy system to manage
122  * reference to the above managers, so it is not necessary to release them
123  * when a servlet is done using them.
124  * <p>
125  * It may be necessary to add the following code to the end of the dispose method of any
126  * servlets referencing any of the above proxies. This is because on some containers,
127  * like Tomcat, the classloader is immediately invalidated after the last servlet is
128  * disposed. If this happens before the managers have all been disposed, then you may
129  * see errors in the console like: <code>WebappClassLoader: Lifecycle error : CL stopped</code>
130  * <pre>
131  * System.gc();
132  * try
133  * {
134  * Thread.sleep(250);
135  * }
136  * catch ( InterruptedException e ) {}
137  * </pre>
138  * Note that servlets which extend the AbstractComponentManagerServlet will behave correctly.
139  *
140  * @deprecated ECM is no longer supported
141  *
142  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
143  * @version CVS $Revision: 1.4 $ $Date: 2004/02/28 11:47:16 $
144  * @since 4.2
145  */

146 public class ExcaliburComponentManagerServlet
147     extends GenericServlet JavaDoc
148 {
149     private ExcaliburComponentManagerCreator m_componentManagerCreator;
150
151     /** Latch used to shutdown the ExcaliburComponentManagerCreator cleanly. */
152     private Latch m_latch;
153
154     /*---------------------------------------------------------------
155      * Constructors
156      *-------------------------------------------------------------*/

157
158     /*---------------------------------------------------------------
159      * GenericServlet Methods
160      *-------------------------------------------------------------*/

161     /**
162      * Builds the component manager and stores references to the
163      * ComponentManager, LoggerManager, and InstrumentManager into
164      * the ServletContext.
165      *
166      * @param servletConfig Servlet configuration
167      *
168      * @throws ServletException If there are any problems initializing the
169      * servlet.
170      */

171     public void init( ServletConfig JavaDoc servletConfig ) throws ServletException JavaDoc
172     {
173         super.init( servletConfig );
174
175         //System.out.println( "ExcaliburComponentManagerServlet.init() BEGIN" );
176
ServletContext JavaDoc servletContext = getServletContext();
177
178         InputStream JavaDoc loggerManagerConfigStream = null;
179         InputStream JavaDoc roleManagerConfigStream = null;
180         InputStream JavaDoc componentManagerConfigStream = null;
181         InputStream JavaDoc instrumentManagerConfigStream = null;
182         try
183         {
184             loggerManagerConfigStream =
185                 getStreamFromParameter( servletConfig, "logkit", true );
186             roleManagerConfigStream =
187                 getStreamFromParameter( servletConfig, "roles", true );
188             componentManagerConfigStream =
189                 getStreamFromParameter( servletConfig, "components", true );
190             instrumentManagerConfigStream =
191                 getStreamFromParameter( servletConfig, "instrument", false );
192
193             // Create the ComponentManagerCreator
194
try
195             {
196                 m_componentManagerCreator = new ExcaliburComponentManagerCreator(
197                     null,
198                     loggerManagerConfigStream,
199                     roleManagerConfigStream,
200                     componentManagerConfigStream,
201                     instrumentManagerConfigStream );
202             }
203             catch( Exception JavaDoc e )
204             {
205                 String JavaDoc msg = "Unable to create the ComponentManagerCreator. "
206                     + "Most likely a comfiguration problem.";
207                 throw new ServletException JavaDoc( msg, e );
208             }
209         }
210         finally
211         {
212             // Close the resource streams
213
try
214             {
215                 if( loggerManagerConfigStream != null )
216                 {
217                     loggerManagerConfigStream.close();
218                 }
219                 if( roleManagerConfigStream != null )
220                 {
221                     roleManagerConfigStream.close();
222                 }
223                 if( componentManagerConfigStream != null )
224                 {
225                     componentManagerConfigStream.close();
226                 }
227                 if( instrumentManagerConfigStream != null )
228                 {
229                     instrumentManagerConfigStream.close();
230                 }
231             }
232             catch( IOException JavaDoc e )
233             {
234                 throw new ServletException JavaDoc( "Encountered an error closing resource streams.", e );
235             }
236         }
237
238         LoggerManager loggerManager = m_componentManagerCreator.getLoggerManager();
239
240         // A series of ReferenceProxies which will be used to access the ComponentManager
241
// and other managers created by the ComponentManagerCreator must be created.
242
// This is necessary because the order in which servlets are shut down by a
243
// ServletContainer can not be controlled. If a manager is disposed before all
244
// servlets have released their references to it, then errors can result.
245

246         // Create the latch which will manager the ReferenceProxies.
247
m_latch = new Latch( m_componentManagerCreator );
248         m_latch.enableLogging( loggerManager.getLoggerForCategory( "system.ecmservlet" ) );
249
250         // Create the actual ReferenceProxies.
251
ReferenceProxy loggerManagerProxy = m_latch.createProxy(
252             loggerManager, "LoggerManager" );
253         ReferenceProxy serviceManagerProxy = m_latch.createProxy(
254             m_componentManagerCreator.getServiceManager(), "ServiceManager" );
255         ReferenceProxy componentManagerProxy = m_latch.createProxy(
256             m_componentManagerCreator.getComponentManager(), "ComponentManager" );
257         ReferenceProxy instrumentManagerProxy = m_latch.createProxy(
258             m_componentManagerCreator.getInstrumentManager(), "InstrumentManager" );
259
260         // Store references to the proxies in the ServletContext so that other servlets can gain
261
// access to them
262
servletContext.setAttribute( LoggerManager.class.getName(), loggerManagerProxy );
263         servletContext.setAttribute( ServiceManager.class.getName(), serviceManagerProxy );
264         servletContext.setAttribute( ComponentManager.class.getName(), componentManagerProxy );
265         servletContext.setAttribute( InstrumentManager.class.getName(), instrumentManagerProxy );
266
267         //System.out.println( "ExcaliburComponentManagerServlet.init() END" );
268
}
269
270     /**
271      * Called by the servlet container to destroy the servlet.
272      */

273     public void destroy()
274     {
275         //System.out.println( "ExcaliburComponentManagerServlet.destroy() BEGIN" );
276

277         ServletContext JavaDoc servletContext = getServletContext();
278
279         // Remove the references to the managers from the servlet context.
280
servletContext.removeAttribute( LoggerManager.class.getName() );
281         servletContext.removeAttribute( ServiceManager.class.getName() );
282         servletContext.removeAttribute( ComponentManager.class.getName() );
283         servletContext.removeAttribute( InstrumentManager.class.getName() );
284
285         // Tell the latch that we are ready for it do dispose of the ECMC
286
m_latch.requestTrigger();
287
288         //System.out.println( "ExcaliburComponentManagerServlet.destroy() END" );
289
}
290
291     /**
292      * This servlet does not accept requests. It will complain if called.
293      *
294      * @param req servlet request
295      * @param res servlet response
296      *
297      * @throws UnavailableException always
298      */

299     public void service( ServletRequest JavaDoc servletRequest, ServletResponse JavaDoc servletResponse )
300         throws UnavailableException JavaDoc
301     {
302         throw new UnavailableException JavaDoc( getClass().getName() + " does not except service requests." );
303     }
304
305     /*---------------------------------------------------------------
306      * Methods
307      *-------------------------------------------------------------*/

308     /**
309      * Looks up a specified resource name and returns it as an InputStream.
310      * It is the responsibility of the caller to close the stream.
311      *
312      * @param servletConfig ServletConfig.
313      * @param resourceName Name of the resource to be loaded.
314      * @param required True if an error should be thrown if the property is missing.
315      *
316      * @return InputStream used to read the contents of the resource.
317      *
318      * @throws ServletException If the specified resource does not exist,
319      * or could not be opened.
320      */

321     private InputStream JavaDoc getStreamFromParameter( ServletConfig JavaDoc servletConfig,
322                                                 String JavaDoc resourceName,
323                                                 boolean required )
324         throws ServletException JavaDoc
325     {
326
327         String JavaDoc configFileName = servletConfig.getInitParameter( resourceName );
328
329         if( configFileName == null )
330         {
331             if( required )
332             {
333                 throw new ServletException JavaDoc( resourceName
334                                             + " parameter must be provided in servlet configuration." );
335             }
336             else
337             {
338                 return null;
339             }
340         }
341
342         ServletContext JavaDoc servletContext = servletConfig.getServletContext();
343
344         log( "Attempting to access resource: " + configFileName );
345
346         InputStream JavaDoc is = servletContext.getResourceAsStream( configFileName );
347
348         if( is == null )
349         {
350             throw new ServletException JavaDoc( "Resource '" + configFileName + "' is not available." );
351         }
352
353         return is;
354     }
355
356     /*---------------------------------------------------------------
357      * Private Classes
358      *-------------------------------------------------------------*/

359     private static class Latch
360         extends AbstractReferenceProxyLatch
361     {
362         ExcaliburComponentManagerCreator m_componentManagerCreator;
363
364         /*---------------------------------------------------------------
365          * Constructors
366          *-------------------------------------------------------------*/

367         /**
368          * Create a new Latch.
369          *
370          * @param ecmc The ExcaliburComponentManagerCreator to be disposed
371          * when all proxies are done.
372          */

373         Latch( ExcaliburComponentManagerCreator componentManagerCreator )
374         {
375             m_componentManagerCreator = componentManagerCreator;
376         }
377
378         /*---------------------------------------------------------------
379          * AbstractReferenceProxyLatch Methods
380          *-------------------------------------------------------------*/

381         /**
382          * Called when all of the proxies have notified that they are done.
383          */

384         public void triggered()
385             throws Exception JavaDoc
386         {
387             //System.out.println( "ExcaliburComponentManagerServlet.Latch.triggered() BEGIN" );
388
ContainerUtil.shutdown( m_componentManagerCreator );
389             //System.out.println( "ExcaliburComponentManagerServlet.Latch.triggered() END" );
390
}
391     }
392 }
393
Popular Tags