KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > web > WebModuleListener


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.web;
25
26 import java.util.logging.Logger JavaDoc;
27 import java.util.logging.Level JavaDoc;
28 import java.util.ResourceBundle JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.text.MessageFormat JavaDoc;
32 import java.lang.instrument.IllegalClassFormatException JavaDoc;
33 import java.net.URLClassLoader JavaDoc;
34 import java.net.URL JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import javax.servlet.ServletContext JavaDoc;
38 import javax.persistence.spi.ClassTransformer;
39
40 import org.apache.catalina.Globals;
41 import org.apache.catalina.Lifecycle;
42 import org.apache.catalina.LifecycleEvent;
43 import org.apache.catalina.LifecycleListener;
44 import org.apache.catalina.LifecycleException;
45 import org.apache.catalina.Wrapper;
46 import org.apache.catalina.loader.WebappClassLoader;
47 import com.sun.enterprise.deployment.runtime.web.SunWebApp;
48 import com.sun.enterprise.deployment.runtime.web.WebProperty;
49 import com.sun.enterprise.deployment.WebBundleDescriptor;
50 import com.sun.enterprise.deployment.Application;
51 import com.sun.enterprise.deployment.util.WebValidatorWithCL;
52 import com.sun.enterprise.deployment.util.WebBundleVisitor;
53 import com.sun.enterprise.util.logging.IASLevel;
54
55 import com.sun.logging.LogDomains;
56 import com.sun.appserv.web.cache.CacheManager;
57 import com.sun.appserv.server.util.ASClassLoaderUtil;
58 import com.sun.appserv.BytecodePreprocessor;
59 import com.sun.enterprise.web.jsp.ResourceInjectorImpl;
60 import com.sun.enterprise.server.PersistenceUnitLoaderImpl;
61 import com.sun.enterprise.server.PersistenceUnitLoader;
62 import com.sun.enterprise.loader.InstrumentableClassLoader;
63 import com.sun.enterprise.config.ConfigException;
64
65 /**
66  * Startup event listener for a <b>Context</b> that configures the properties
67  * of that Jsp Servlet from sun-web.xml
68  */

69
70 final class WebModuleListener
71     implements LifecycleListener {
72
73     /**
74      * The logger used to log messages
75      */

76     private static Logger JavaDoc _logger;
77
78     /**
79      * This indicates whether debug logging is on or not
80      */

81     private static boolean _debugLog;
82
83     /**
84      * The instance classpath, which is composed of the pathnames of
85      * domain_root/lib/classes and domain_root/lib/[*.jar|*.zip] (in this
86      * order), separated by the path-separator character.
87      */

88     private String JavaDoc instanceClassPath;
89
90     /**
91      * Descriptor object associated with this web application.
92      * Used for loading persistence units.
93      */

94     private WebBundleDescriptor wbd;
95
96     /**
97      * The exploded location for this web module.
98      * Note this is not the generated location.
99      */

100     private String JavaDoc explodedLocation;
101
102     /**
103      * Constructor.
104      *
105      * @param instanceClassPath The instance classpath, which is composed of
106      * the pathnames of domain_root/lib/classes and
107      * domain_root/lib/[*.jar|*.zip] (in this order), separated by the
108      * path-separator character.
109      * @param explodedLocation The location where this web module is exploded
110      * @param wbd descriptor for this module.
111      */

112     public WebModuleListener(String JavaDoc instanceClassPath,
113                              String JavaDoc explodedLocation,
114                              WebBundleDescriptor wbd) {
115         this.instanceClassPath = instanceClassPath;
116         this.wbd = wbd;
117         this.explodedLocation = explodedLocation;
118     }
119
120
121     /**
122      * Process the START event for an associated WebModule
123      * @param event The lifecycle event that has occurred
124      */

125     public void lifecycleEvent(LifecycleEvent event) {
126
127         if (_logger == null) {
128             _logger = LogDomains.getLogger(LogDomains.WEB_LOGGER);
129             _debugLog = _logger.isLoggable(Level.FINE);
130         }
131
132         WebModule webModule;
133
134         // Identify the context we are associated with
135
try {
136             webModule = (WebModule) event.getLifecycle();
137         } catch (ClassCastException JavaDoc e) {
138             _logger.log(Level.WARNING, "webmodule.listener.classcastException",
139                                         event.getLifecycle());
140             return;
141         }
142
143         // Process the event that has occurred
144
if (event.getType().equals(Lifecycle.START_EVENT)) {
145             // post processing DOL object for standalone web module
146
if (wbd != null && wbd.getApplication() != null &&
147                 wbd.getApplication().isVirtual()) {
148                 wbd.setClassLoader(webModule.getLoader().getClassLoader());
149                 wbd.visit((WebBundleVisitor) new WebValidatorWithCL());
150             }
151             
152             loadPersistenceUnits(webModule);
153             configureDefaultServlet(webModule);
154             configureJspParameters(webModule);
155             startCacheManager(webModule);
156         } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
157             unloadPersistenceUnits(webModule);
158             stopCacheManager(webModule);
159         }
160     }
161
162     private void loadPersistenceUnits(final WebModule webModule) {
163         _logger.logp(Level.FINE, "WebModuleListener", "loadPersistenceUnits",
164                 "wbd = {0} for {1}", new Object JavaDoc[]{wbd, webModule.getName()});
165         if(wbd == null) {
166             // for some system app like adminGUI, wbd is null
167
return;
168         }
169         final Application application = wbd.getApplication();
170         // load PUs only for standaalone wars.
171
// embedded wars are taken care of in ApplicationLoader.
172
if(application != null && application.isVirtual()) {
173             try{
174                 new PersistenceUnitLoaderImpl().load(new ApplicationInfoImpl(
175                         explodedLocation, wbd, webModule));
176             } catch(Exception JavaDoc e){
177                 throw new RuntimeException JavaDoc(e);
178             }
179         }
180     }
181
182     private boolean unloadPersistenceUnits(final WebModule webModule) {
183         _logger.logp(Level.FINE, "WebModuleListener", "unloadPersistenceUnits",
184                 "wbd = {0} for {1}", new Object JavaDoc[]{wbd, webModule.getName()});
185         if(wbd == null) {
186             // for some system app like adminGUI, wbd is null
187
return true;
188         }
189         final Application application = wbd.getApplication();
190         // unload PUs only for standaalone wars.
191
// embedded wars are taken care of in ApplicationLoader.
192
if(application != null && application.isVirtual()) {
193             try{
194                 new PersistenceUnitLoaderImpl().unload(new ApplicationInfoImpl(
195                         explodedLocation, wbd, webModule));
196             } catch(Exception JavaDoc e){
197                 _logger.log(Level.WARNING, e.getMessage(), e);
198                 return false;
199             }
200         }
201         return true;
202     }
203
204     /**
205      * implementation of {@link ApplicationInfoImpl}.
206      */

207     private static class ApplicationInfoImpl
208             implements PersistenceUnitLoader.ApplicationInfo {
209         private WebBundleDescriptor wbd;
210         private String JavaDoc location;
211         private InstrumentableClassLoader classLoader;
212         public ApplicationInfoImpl(String JavaDoc location, WebBundleDescriptor wbd, WebModule wm) {
213             this.wbd = wbd;
214             this.location = location;
215             this.classLoader = new InstrumentableWebappClassLoader(
216                     WebappClassLoader.class.cast(wm.getLoader().getClassLoader()));
217         }
218
219         public Application getApplication() {
220             return wbd.getApplication();
221         }
222
223         public InstrumentableClassLoader getClassLoader() {
224             return classLoader;
225         }
226
227         public String JavaDoc getApplicationLocation() {
228             return location;
229         }
230
231     } // class ApplicationInfoImpl
232

233     /**
234      * This class adapts WebappClassLoader to InstrumentableClassLoader that
235      * is used by {@link PersistenceUnitLoader}.
236      * It extends ClassLoader and overrides the public interfaces
237      * of ClassLoader to delegate the calls to WebappClassLoader.
238      */

239     private static final class InstrumentableWebappClassLoader extends ClassLoader JavaDoc
240             implements InstrumentableClassLoader {
241
242         // the delegate
243
private final WebappClassLoader webappClassLoader;
244
245         public InstrumentableWebappClassLoader(WebappClassLoader webappClassLoader) {
246             // set the delegate's parent as its parent
247
super(webappClassLoader.getParent());
248             this.webappClassLoader = webappClassLoader;
249         }
250
251         // implementation of InstrumentableClassLoader interface methods.
252

253         public ClassLoader JavaDoc copy() {
254             _logger.entering("WebModuleListener$InstrumentableWebappClassLoader", "copy");
255             // set getParent() as the parent of the cloned class loader
256
return new URLClassLoader JavaDoc(webappClassLoader.getURLs(), getParent());
257         }
258
259         public void addTransformer(final ClassTransformer transformer) {
260             webappClassLoader.addByteCodePreprocessor(new BytecodePreprocessor(){
261                 /*
262                  * This class adapts ClassFileTransformer to ByteCodePreprocessor that
263                  * is used inside WebappClassLoader.
264                  */

265
266                 public boolean initialize(Hashtable JavaDoc parameters) {
267                     return true;
268                 }
269
270                 public byte[] preprocess(String JavaDoc resourceName, byte[] classBytes) {
271                     try {
272                         // convert java/lang/Object.class to java/lang/Object
273
String JavaDoc classname = resourceName.substring(0,
274                                 resourceName.length() - 6); // ".class" size = 6
275
byte[] newBytes = transformer.transform(
276                                 webappClassLoader, classname, null, null, classBytes);
277                         // ClassFileTransformer returns null if no transformation
278
// took place, where as ByteCodePreprocessor is expected
279
// to return non-null byte array.
280
return newBytes == null ? classBytes : newBytes;
281                     } catch (IllegalClassFormatException JavaDoc e) {
282                         _logger.logp(Level.WARNING,
283                                 "WebModuleListener$InstrumentableClassLoader$BytecodePreprocessor",
284                                 "preprocess", e.getMessage());
285                         throw new RuntimeException JavaDoc(e);
286                     }
287                 }
288             });
289         }
290
291         // override public interfaces of java.lang.ClassLoader
292
// to delegate the calls to webappClassLoader
293

294         @Override JavaDoc public Class JavaDoc<?> loadClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
295             return webappClassLoader.loadClass(name);
296         }
297
298         @Override JavaDoc public URL JavaDoc getResource(String JavaDoc name) {
299             return webappClassLoader.getResource(name);
300         }
301
302         @Override JavaDoc public Enumeration JavaDoc<URL JavaDoc> getResources(String JavaDoc name)
303                 throws IOException JavaDoc {
304             return webappClassLoader.getResources(name);
305         }
306
307         @Override JavaDoc public InputStream JavaDoc getResourceAsStream(String JavaDoc name) {
308             return webappClassLoader.getResourceAsStream(name);
309         }
310
311         @Override JavaDoc public synchronized void setDefaultAssertionStatus(boolean enabled) {
312             webappClassLoader.setDefaultAssertionStatus(enabled);
313         }
314
315         @Override JavaDoc public synchronized void setPackageAssertionStatus(
316                 String JavaDoc packageName, boolean enabled) {
317             webappClassLoader.setPackageAssertionStatus(packageName, enabled);
318         }
319
320         @Override JavaDoc public synchronized void setClassAssertionStatus(
321                 String JavaDoc className, boolean enabled) {
322             webappClassLoader.setClassAssertionStatus(className, enabled);
323         }
324
325         @Override JavaDoc public synchronized void clearAssertionStatus() {
326             webappClassLoader.clearAssertionStatus();
327         }
328
329         @Override JavaDoc public String JavaDoc toString() {
330             StringBuilder JavaDoc sb = new StringBuilder JavaDoc("InstrumentableWebappClassLoader\r\n");
331             sb.append(" Parent -> ");
332             sb.append(webappClassLoader);
333             return sb.toString();
334         }
335
336     } // class InstrumentableWebappClassLoader
337

338     //------------------------------------------------------- Private Methods
339

340     /**
341      * Configure the jsp config settings for the jspServlet using the values
342      * in sun-web.xml's jsp-config
343      */

344     private void configureJspParameters(WebModule webModule) {
345
346         SunWebApp bean = webModule.getIasWebAppConfigBean();
347
348         // Find the default jsp servlet
349
String JavaDoc name = webModule.findServletMapping(Constants.JSP_URL_PATTERN);
350         Wrapper wrapper = (Wrapper)webModule.findChild(name);
351         if (wrapper == null)
352             return;
353
354         String JavaDoc servletClass = wrapper.getServletClass();
355         // If the jsp maps to the default JspServlet, then add
356
// the init parameters
357
if (servletClass != null
358                 && servletClass.equals(Constants.APACHE_JSP_SERVLET_CLASS)) {
359
360             if (webModule.getTldValidation()) {
361                 wrapper.addInitParameter("enableTldValidation", "true");
362             }
363             if (bean != null && bean.getJspConfig() != null) {
364                 WebProperty[] props = bean.getJspConfig().getWebProperty();
365                 for (int i = 0; i < props.length; i++) {
366                     String JavaDoc pname = props[i].getAttributeValue("name");
367                     String JavaDoc pvalue = props[i].getAttributeValue("value");
368                     if (_debugLog) {
369                         _logger.fine("jsp-config property for ["
370                                      + webModule.getID() + "] is [" + pname
371                                      + "] = [" + pvalue + "]");
372                     }
373                     wrapper.addInitParameter(pname, pvalue);
374                 }
375             }
376            
377             // Override any log setting with the container wide logging level
378
wrapper.addInitParameter("logVerbosityLevel",getJasperLogLevel());
379
380             wrapper.addInitParameter("com.sun.appserv.jsp.resource.injector",
381                                      ResourceInjectorImpl.class.getName());
382
383             // START SJSAS 6311155
384
String JavaDoc sysClassPath = ASClassLoaderUtil.getWebModuleClassPath(webModule.getID());
385             if (_logger.isLoggable(Level.FINE)) {
386                 _logger.fine(" sysClasspath for " + webModule.getID() + " is \n"
387                                                                + sysClassPath + "\n");
388             }
389             if (instanceClassPath != null
390                     && instanceClassPath.length() > 0) {
391                 sysClassPath += instanceClassPath;
392             }
393             wrapper.addInitParameter("com.sun.appserv.jsp.classpath",
394                                      sysClassPath);
395             // END SJSAS 6311155
396
}
397     }
398
399     /**
400      * Determine the debug setting for JspServlet based on the iAS log
401      * level.
402      */

403     private String JavaDoc getJasperLogLevel() {
404         Level JavaDoc level = _logger.getLevel();
405         if (level.equals((Level JavaDoc)IASLevel.FATAL))
406             return "fatal";
407         else if (level.equals(Level.WARNING))
408             return "warning";
409         else if (level.equals(Level.FINE))
410             return "information";
411         else if (level.equals(Level.FINER) || level.equals(Level.FINEST))
412             return "debug";
413         else
414             return "warning";
415     }
416
417     private void startCacheManager(WebModule webModule) {
418
419         SunWebApp bean = webModule.getIasWebAppConfigBean();
420
421         // Configure the cache, cache-mapping and other settings
422
if (bean != null) {
423             CacheManager cm = null;
424             try {
425                 cm = CacheModule.configureResponseCache(webModule, bean);
426             } catch (Exception JavaDoc ee) {
427                 _logger.log(Level.WARNING,
428                            "webmodule.listener.cachemgrException", ee);
429             }
430         
431             if (cm != null) {
432                 try {
433                     // first start the CacheManager, if enabled
434
cm.start();
435                     if (_debugLog) {
436                         _logger.fine("Cache Manager started");
437                     }
438                     // set this manager as a context attribute so that
439
// caching filters/tags can find it
440
ServletContext JavaDoc ctxt = webModule.getServletContext();
441                     ctxt.setAttribute(CacheManager.CACHE_MANAGER_ATTR_NAME, cm);
442
443                 } catch (LifecycleException ee) {
444                     _logger.log(Level.WARNING, ee.getMessage(),
445                                                ee.getThrowable());
446                 }
447             }
448         }
449     }
450
451     private void stopCacheManager(WebModule webModule) {
452         ServletContext JavaDoc ctxt = webModule.getServletContext();
453         CacheManager cm = (CacheManager)ctxt.getAttribute(
454                                         CacheManager.CACHE_MANAGER_ATTR_NAME);
455         if (cm != null) {
456             try {
457                 cm.stop();
458                 if (_debugLog) {
459                     _logger.fine("Cache Manager stopped");
460                 }
461                 ctxt.removeAttribute(CacheManager.CACHE_MANAGER_ATTR_NAME);
462             } catch (LifecycleException ee) {
463                 _logger.log(Level.WARNING, ee.getMessage(), ee.getThrowable());
464             }
465         }
466     }
467
468
469     /**
470      * Configures the given web module's DefaultServlet with the
471      * applicable web properties from sun-web.xml.
472      */

473     private void configureDefaultServlet(WebModule webModule) {
474
475         // Find the DefaultServlet
476
Wrapper wrapper = (Wrapper)webModule.findChild("default");
477         if (wrapper == null) {
478             return;
479         }
480
481         String JavaDoc servletClass = wrapper.getServletClass();
482         if (servletClass == null
483                 || !servletClass.equals(Globals.DEFAULT_SERVLET_CLASS_NAME)) {
484             return;
485         }
486
487         String JavaDoc fileEncoding = webModule.getFileEncoding();
488         if (fileEncoding != null) {
489             wrapper.addInitParameter("fileEncoding", fileEncoding);
490         }
491     }
492 }
493
Popular Tags