KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jfun > yan > web > YanLoader


1 package jfun.yan.web;
2
3 import java.io.InputStream JavaDoc;
4 import javax.servlet.ServletContext JavaDoc;
5
6 import jfun.util.ClassLoaderUtils;
7 import jfun.yan.Container;
8 import jfun.yan.YanException;
9 import jfun.yan.lifecycle.DefaultLifecycleManager;
10 import jfun.yan.lifecycle.LifecycleManager;
11 import jfun.yan.util.resource.ClassLoader2ResourceLoader;
12 import jfun.yan.util.resource.ResourceLoader;
13 import jfun.yan.xml.NutsProcessor;
14 import jfun.yan.xml.nuts.spring.SpringNuts;
15 /**
16  * This class is responsible for setting up web integration for Yan.
17  * <p>
18  * @author Ben Yu
19  * Jan 17, 2006 1:27:59 PM
20  */

21 public class YanLoader {
22
23   /**
24    * Name of servlet context parameter that can specify the configuration file
25    * for the root container, falling back to {@link #DEFAULT_CONFIG_FILE}
26    * otherwise.
27    */

28   public static final String JavaDoc CONFIG_FILE_PARAM = "yanConfigFile";
29   /**
30    * Name of the servlet context parameter that specifies whether Spring
31    * framework integration is required. The default is "false".
32    */

33   public static final String JavaDoc USE_SPRING = "yanSpringIntegration";
34   /**
35    * The value "true" that should be specified for {@link #USE_SPRING}
36    * if Spring framework integration is desired.
37    */

38   public static final String JavaDoc TRUE = Boolean.valueOf(true).toString();
39   /**
40    * The default location of the yan configuration file.
41    */

42   public static final String JavaDoc DEFAULT_CONFIG_FILE = "/WEB-INF/yan.xml";
43   /**
44    * The service key for the ServletContext object.
45    */

46   public static final String JavaDoc SERVLET_CONTEXT_KEY = "jfun.yan.web.ServletContext";
47   /**
48    * The name of the servlet context attribut that holds the Container instance.
49    * Equal to the fully qualified class name of {@link Container}.
50    */

51   public static final String JavaDoc CONTAINER_ROOT = Container.class.getName();
52   /**
53    * The name of the servlet context attribute that holds the life cycle manager
54    * instance. Equal to the fully qualified name of {@link LifecycleManager}.
55    */

56   public static final String JavaDoc LIFECYCLE_MANAGER_ROOT = LifecycleManager.class.getName();
57   /**
58    * The default xml file that configures the non-spring nut classes.
59    */

60   public static final String JavaDoc DEFAULT_NUTS_FILE = "jfun/yan/web/webnuts.xml";
61   /**
62    * The default xml file that configures spring aware nut classes.
63    */

64   public static final String JavaDoc DEFAULT_SPRING_NUTS_FILE = "jfun/yan/web/webspringnuts.xml";
65   
66   private NutsProcessor processor;
67   private Container yan;
68   private DefaultLifecycleManager lifecycle_manager;
69   /**
70    * Initialize this object by instantiating container and life cycle manager.
71    * Relevant servlet context parameters are read.
72    * @param ctxt the servlet context object.
73    * @return the Container object instantiated.
74    */

75   public Container initContainer(ServletContext JavaDoc ctxt){
76     return initContainer(
77         ClassLoaderUtils.guessClassLoader(getClass().getClassLoader()),
78         ctxt);
79   }
80   /**
81    * Call start on the life cycle manager.
82    */

83   public synchronized void start()
84   throws Throwable JavaDoc{
85     if(lifecycle_manager!=null)
86       lifecycle_manager.start();
87   }
88   /**
89    * Call stop on the life cycle manager.
90    */

91   public synchronized void stop()throws Throwable JavaDoc{
92     if(lifecycle_manager != null)
93       lifecycle_manager.stop();
94   }
95   /**
96    * Initialize this object by instantiating container and life cycle manager.
97    * Relevant servlet context parameters are read.
98    * <p>
99    * This implementation calls {@link #process(ClassLoader, ServletContext)}
100    * for interpreting the configuration file and obtaining the Container instance
101    * and LifecycleManager instance.
102    * </p>
103    * @param cloader the ClassLoader used to load component classes.
104    * @param servletContext the servlet context object.
105    * @return the Container object instantiated.
106    * null is returned if configuration file not found.
107    */

108   public synchronized Container initContainer(ClassLoader JavaDoc cloader, ServletContext JavaDoc servletContext){
109     servletContext.log("Loading Nuts container");
110     if(processor!=null){
111       throw new IllegalStateException JavaDoc("YanLoader already initialized.");
112     }
113     try {
114       this.processor = process(cloader, servletContext);
115       if(this.processor==null){
116         return null;
117       }
118       
119       Container parent = loadParentContainer(servletContext);
120       this.yan = parent!=null?processor.getContainer().inherit(parent)
121         : processor.getContainer();
122       this.lifecycle_manager = processor.getLifecycleManager();
123       servletContext.setAttribute(CONTAINER_ROOT, this.yan);
124       servletContext.setAttribute(LIFECYCLE_MANAGER_ROOT, this.yan);
125       processor.preInstantiate(this.yan);
126       return this.yan;
127     }
128     catch (RuntimeException JavaDoc ex) {
129       servletContext.log("Container initialization failed", ex);
130       servletContext.setAttribute(CONTAINER_ROOT, ex);
131       throw ex;
132     }
133     catch(Exception JavaDoc e){
134       servletContext.log("Container initialization failed", e);
135       servletContext.setAttribute(CONTAINER_ROOT, e);
136       throw new YanException(e);
137     }
138     catch (Error JavaDoc err) {
139       servletContext.log("Container initialization error", err);
140       servletContext.setAttribute(CONTAINER_ROOT, err);
141       throw err;
142     }
143   }
144
145   /**
146    * Load the parent Container object that's shared among web applications.
147    * @param servletContext the servlet context.
148    * @return the Container object. or null if not found.
149    */

150   protected Container loadParentContainer(ServletContext JavaDoc servletContext)
151   throws Exception JavaDoc{
152     return null;
153   }
154   /**
155    * Create a NutsProcessor object based on the configuration in ServletContext.
156    * The configuration file is also parsed and interpreted.
157    * <p>
158    * This default implementation delegates to {@link #getNutsProcessor(ClassLoader, ResourceLoader, ServletContext)}
159    * for constructing the NutsProcessor object.
160    * </p>
161    * <p>
162    * If no ServletContext component is registered, the current ServletContext object
163    * is registered as a component in the container.
164    * </p>
165    * @param cloader the ClassLoader object used to load component classes.
166    * @param ctxt the ServletContext object.
167    * @return the populated NutsProcessor object.
168    * @throws Exception any error.
169    */

170   protected NutsProcessor process(ClassLoader JavaDoc cloader, ServletContext JavaDoc ctxt)
171   throws Exception JavaDoc{
172     String JavaDoc config_file = ctxt.getInitParameter(CONFIG_FILE_PARAM);
173     if(config_file==null){
174       ctxt.log(CONFIG_FILE_PARAM
175           +" not specified, looking for default "+DEFAULT_CONFIG_FILE);
176       config_file = DEFAULT_CONFIG_FILE;
177     }
178
179     final ResourceLoader rloader = new ServletContextResourceLoader(ctxt,
180         new ClassLoader2ResourceLoader(cloader));
181     final InputStream JavaDoc in = rloader.getResourceAsStream(config_file);
182     if(in == null){
183       ctxt.log("yan configuration file "+config_file+" not found.");
184       return null;
185     }
186     try{
187       final NutsProcessor proc = getNutsProcessor(cloader, rloader, ctxt);
188       proc.process(rloader.getResource(config_file), in);
189       registerServletContext(proc.getContainer(), ctxt);
190       return proc;
191     }
192     finally{
193       in.close();
194     }
195   }
196   /**
197    * Register the ServletContext into the container using
198    * either {@link WebUtils#DEFAULT_SERVLET_CONTEXT_PROPERTY} or
199    * else ServletContext.class as long as there's no ServletContext
200    * component already registered.
201    * @param container the Yan container object.
202    * @param ctxt the ServletContext object.
203    */

204   protected static void registerServletContext(Container container, ServletContext JavaDoc ctxt){
205     if(!container.containsType(ServletContext JavaDoc.class)){
206       if(container.containsKey(WebUtils.DEFAULT_SERVLET_CONTEXT_PROPERTY)){
207         container.registerValue(ServletContext JavaDoc.class, ctxt);
208       }
209       else{
210         container.registerValue(WebUtils.DEFAULT_SERVLET_CONTEXT_PROPERTY, ctxt);
211       }
212     }
213   }
214   /**
215    * Construct a NutsProcessor object based on the configuration information
216    * stored in ServletContext. And then call {@link #decorateProcessor(NutsProcessor, ServletContext)}
217    * to decorate it.
218    * @param cloader the ClassLoader object used to load component class.
219    * @param rloader the ResourceLoader object used to load resource.
220    * @param ctxt the ServletContext object.
221    * @return the result NutsProcessor object.
222    * @throws Exception any error.
223    */

224   protected NutsProcessor getNutsProcessor(ClassLoader JavaDoc cloader, ResourceLoader rloader,
225       ServletContext JavaDoc ctxt)throws Exception JavaDoc{
226     final NutsProcessor proc = new NutsProcessor(cloader, rloader);
227     decorateProcessor(proc, ctxt);
228     return proc;
229   }
230   /**
231    * Decorate a NutsProcessor object by adding or removing features.
232    * <p>
233    * This default implementation replaces &lt;bean&gt;, &lt;ctor&gt;
234    * and &lt;method&gt; tags with the ones that're aware of the ServletContext.
235    * </p>
236    * <p>
237    * It does so by registering the ServletContext as a service under {@link #SERVLET_CONTEXT_KEY}.
238    * The customized tags then look up this service and call "setServletContext()" or
239    * any other specified receiver method to set this dependency.
240    * </p>
241    * <p>
242    * Based on whether {@link #USE_SPRING} parameter is set in ServletContext,
243    * this implementation calls either {@link #setSpringAware(NutsProcessor, ServletContext)}
244    * or {@link #setWebAware(NutsProcessor, ServletContext)} to do the decoration.
245    * </p>
246    * <p>
247    * Subclasses can override this method to provide customized decoration.
248    * </p>
249    * @param processor the NutsProcessor object to decorate.
250    * @param ctxt the ServletContext object.
251    * @throws Exception any error.
252    */

253   protected void decorateProcessor(NutsProcessor processor, ServletContext JavaDoc ctxt)
254   throws Exception JavaDoc{
255     processor.registerService(SERVLET_CONTEXT_KEY, ctxt);
256     String JavaDoc spring_integration = ctxt.getInitParameter(USE_SPRING);
257     if(spring_integration!=null && TRUE.equals(spring_integration)){
258       setSpringAware(processor, ctxt);
259     }
260     else{
261       setWebAware(processor, ctxt);
262     }
263   }
264   /**
265    * Decorate NutsProcessor object with nut classes that integrates Spring framework
266    * and also aware of the web infrastructure, i.e. ServletContext.
267    * @param processor the NutsProcessor object to decorate.
268    * @param ctxt the ServletContext object.
269    * @throws Exception any error.
270    */

271   protected void setSpringAware(NutsProcessor processor, ServletContext JavaDoc ctxt)
272   throws Exception JavaDoc{
273     SpringNuts.setSpringAware("yan_web_spring", processor, DEFAULT_SPRING_NUTS_FILE);
274   }
275   /**
276    * Decorate NutsProcessor object with nut classes that are aware of the web infrastructure, i.e. ServletContext.
277    * @param processor the NutsProcessor object to decorate.
278    * @param ctxt the ServletContext object.
279    * @throws Exception any error.
280    */

281   protected void setWebAware(NutsProcessor processor, ServletContext JavaDoc ctxt)
282   throws Exception JavaDoc{
283     processor.loadNutsMetaResource(DEFAULT_NUTS_FILE);
284   }
285   /**
286    * Destroy the container.
287    * @param servletContext the servlet context.
288    */

289   public synchronized void destroy(ServletContext JavaDoc servletContext){
290     if(lifecycle_manager==null) return;
291     servletContext.log("Closing Yan root container");
292     try{
293       lifecycle_manager.dispose();
294       this.lifecycle_manager = null;
295       this.yan = null;
296       this.processor = null;
297     }
298     catch(Error JavaDoc e){
299       servletContext.log("error in container shutdown", e);
300       throw e;
301     }
302     catch(Throwable JavaDoc e){
303       servletContext.log("error in container shutdown", e);
304     }
305   }
306
307 }
308
Popular Tags