Source Code Cross Referenced for WebappLoader.java in  » Sevlet-Container » tomcat-catalina » org » apache » catalina » loader » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » tomcat catalina » org.apache.catalina.loader 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999,2004 The Apache Software Foundation.
0003:         * 
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         * 
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.apache.catalina.loader;
0018:
0019:        import java.beans.PropertyChangeEvent;
0020:        import java.beans.PropertyChangeListener;
0021:        import java.beans.PropertyChangeSupport;
0022:        import java.io.File;
0023:        import java.io.FileOutputStream;
0024:        import java.io.FilePermission;
0025:        import java.io.IOException;
0026:        import java.io.InputStream;
0027:        import java.io.OutputStream;
0028:        import java.lang.reflect.Constructor;
0029:        import java.lang.reflect.Method;
0030:        import java.net.MalformedURLException;
0031:        import java.net.URL;
0032:        import java.net.URLClassLoader;
0033:        import java.net.URLStreamHandlerFactory;
0034:        import java.util.ArrayList;
0035:        import java.util.jar.JarFile;
0036:
0037:        import javax.management.MBeanRegistration;
0038:        import javax.management.MBeanServer;
0039:        import javax.management.ObjectName;
0040:        import javax.naming.Binding;
0041:        import javax.naming.NameClassPair;
0042:        import javax.naming.NamingEnumeration;
0043:        import javax.naming.NamingException;
0044:        import javax.naming.directory.DirContext;
0045:        import javax.servlet.ServletContext;
0046:
0047:        import org.apache.catalina.Container;
0048:        import org.apache.catalina.Context;
0049:        import org.apache.catalina.DefaultContext;
0050:        import org.apache.catalina.Engine;
0051:        import org.apache.catalina.Globals;
0052:        import org.apache.catalina.Lifecycle;
0053:        import org.apache.catalina.LifecycleException;
0054:        import org.apache.catalina.LifecycleListener;
0055:        import org.apache.catalina.Loader;
0056:        import org.apache.catalina.Logger;
0057:        import org.apache.catalina.core.StandardContext;
0058:        import org.apache.catalina.util.LifecycleSupport;
0059:        import org.apache.catalina.util.StringManager;
0060:        import org.apache.commons.modeler.Registry;
0061:        import org.apache.naming.resources.DirContextURLStreamHandler;
0062:        import org.apache.naming.resources.DirContextURLStreamHandlerFactory;
0063:        import org.apache.naming.resources.Resource;
0064:
0065:        /**
0066:         * Classloader implementation which is specialized for handling web
0067:         * applications in the most efficient way, while being Catalina aware (all
0068:         * accesses to resources are made through the DirContext interface).
0069:         * This class loader supports detection of modified
0070:         * Java classes, which can be used to implement auto-reload support.
0071:         * <p>
0072:         * This class loader is configured by adding the pathnames of directories,
0073:         * JAR files, and ZIP files with the <code>addRepository()</code> method,
0074:         * prior to calling <code>start()</code>.  When a new class is required,
0075:         * these repositories will be consulted first to locate the class.  If it
0076:         * is not present, the system class loader will be used instead.
0077:         *
0078:         * @author Craig R. McClanahan
0079:         * @author Remy Maucherat
0080:         * @version $Revision: 1.27 $ $Date: 2004/03/02 12:31:57 $
0081:         */
0082:
0083:        public class WebappLoader implements  Lifecycle, Loader,
0084:                PropertyChangeListener, MBeanRegistration {
0085:
0086:            // ----------------------------------------------------------- Constructors
0087:
0088:            /**
0089:             * Construct a new WebappLoader with no defined parent class loader
0090:             * (so that the actual parent will be the system class loader).
0091:             */
0092:            public WebappLoader() {
0093:
0094:                this (null);
0095:
0096:            }
0097:
0098:            /**
0099:             * Construct a new WebappLoader with the specified class loader
0100:             * to be defined as the parent of the ClassLoader we ultimately create.
0101:             *
0102:             * @param parent The parent class loader
0103:             */
0104:            public WebappLoader(ClassLoader parent) {
0105:                super ();
0106:                this .parentClassLoader = parent;
0107:            }
0108:
0109:            // ----------------------------------------------------- Instance Variables
0110:
0111:            /**
0112:             * First load of the class.
0113:             */
0114:            private static boolean first = true;
0115:
0116:            /**
0117:             * The class loader being managed by this Loader component.
0118:             */
0119:            private WebappClassLoader classLoader = null;
0120:
0121:            /**
0122:             * The Container with which this Loader has been associated.
0123:             */
0124:            private Container container = null;
0125:
0126:            /**
0127:             * The debugging detail level for this component.
0128:             */
0129:            private int debug = 0;
0130:
0131:            /**
0132:             * The DefaultContext with which this Loader is associated.
0133:             */
0134:            protected DefaultContext defaultContext = null;
0135:
0136:            /**
0137:             * The "follow standard delegation model" flag that will be used to
0138:             * configure our ClassLoader.
0139:             */
0140:            private boolean delegate = false;
0141:
0142:            /**
0143:             * The descriptive information about this Loader implementation.
0144:             */
0145:            private static final String info = "org.apache.catalina.loader.WebappLoader/1.0";
0146:
0147:            /**
0148:             * The lifecycle event support for this component.
0149:             */
0150:            protected LifecycleSupport lifecycle = new LifecycleSupport(this );
0151:
0152:            /**
0153:             * The Java class name of the ClassLoader implementation to be used.
0154:             * This class should extend WebappClassLoader, otherwise, a different 
0155:             * loader implementation must be used.
0156:             */
0157:            private String loaderClass = "org.apache.catalina.loader.WebappClassLoader";
0158:
0159:            /**
0160:             * The parent class loader of the class loader we will create.
0161:             */
0162:            private ClassLoader parentClassLoader = null;
0163:
0164:            /**
0165:             * The reloadable flag for this Loader.
0166:             */
0167:            private boolean reloadable = false;
0168:
0169:            /**
0170:             * The set of repositories associated with this class loader.
0171:             */
0172:            private String repositories[] = new String[0];
0173:
0174:            /**
0175:             * The string manager for this package.
0176:             */
0177:            protected static final StringManager sm = StringManager
0178:                    .getManager(Constants.Package);
0179:
0180:            /**
0181:             * Has this component been started?
0182:             */
0183:            private boolean started = false;
0184:
0185:            /**
0186:             * The property change support for this component.
0187:             */
0188:            protected PropertyChangeSupport support = new PropertyChangeSupport(
0189:                    this );
0190:
0191:            /**
0192:             * Classpath set in the loader.
0193:             */
0194:            private String classpath = null;
0195:
0196:            /**
0197:             * Repositories that are set in the loader, for JMX.
0198:             */
0199:            private ArrayList loaderRepositories = null;
0200:
0201:            // ------------------------------------------------------------- Properties
0202:
0203:            /**
0204:             * Return the Java class loader to be used by this Container.
0205:             */
0206:            public ClassLoader getClassLoader() {
0207:
0208:                return ((ClassLoader) classLoader);
0209:
0210:            }
0211:
0212:            /**
0213:             * Return the Container with which this Logger has been associated.
0214:             */
0215:            public Container getContainer() {
0216:
0217:                return (container);
0218:
0219:            }
0220:
0221:            /**
0222:             * Set the Container with which this Logger has been associated.
0223:             *
0224:             * @param container The associated Container
0225:             */
0226:            public void setContainer(Container container) {
0227:
0228:                // Deregister from the old Container (if any)
0229:                if ((this .container != null)
0230:                        && (this .container instanceof  Context))
0231:                    ((Context) this .container)
0232:                            .removePropertyChangeListener(this );
0233:
0234:                // Process this property change
0235:                Container oldContainer = this .container;
0236:                this .container = container;
0237:                support.firePropertyChange("container", oldContainer,
0238:                        this .container);
0239:
0240:                // Register with the new Container (if any)
0241:                if ((this .container != null)
0242:                        && (this .container instanceof  Context)) {
0243:                    setReloadable(((Context) this .container).getReloadable());
0244:                    ((Context) this .container).addPropertyChangeListener(this );
0245:                }
0246:
0247:            }
0248:
0249:            /**
0250:             * Return the DefaultContext with which this Loader is associated.
0251:             * XXX What is that ???
0252:             */
0253:            public DefaultContext getDefaultContext() {
0254:
0255:                return (this .defaultContext);
0256:
0257:            }
0258:
0259:            /**
0260:             * Set the DefaultContext with which this Loader is associated.
0261:             *
0262:             * @param defaultContext The newly associated DefaultContext
0263:             */
0264:            public void setDefaultContext(DefaultContext defaultContext) {
0265:
0266:                DefaultContext oldDefaultContext = this .defaultContext;
0267:                this .defaultContext = defaultContext;
0268:                support.firePropertyChange("defaultContext", oldDefaultContext,
0269:                        this .defaultContext);
0270:
0271:            }
0272:
0273:            /**
0274:             * Return the debugging detail level for this component.
0275:             */
0276:            public int getDebug() {
0277:
0278:                return (this .debug);
0279:
0280:            }
0281:
0282:            /**
0283:             * Set the debugging detail level for this component.
0284:             *
0285:             * @param debug The new debugging detail level
0286:             */
0287:            public void setDebug(int debug) {
0288:
0289:                int oldDebug = this .debug;
0290:                this .debug = debug;
0291:                support.firePropertyChange("debug", new Integer(oldDebug),
0292:                        new Integer(this .debug));
0293:
0294:            }
0295:
0296:            /**
0297:             * Return the "follow standard delegation model" flag used to configure
0298:             * our ClassLoader.
0299:             */
0300:            public boolean getDelegate() {
0301:
0302:                return (this .delegate);
0303:
0304:            }
0305:
0306:            /**
0307:             * Set the "follow standard delegation model" flag used to configure
0308:             * our ClassLoader.
0309:             *
0310:             * @param delegate The new flag
0311:             */
0312:            public void setDelegate(boolean delegate) {
0313:
0314:                boolean oldDelegate = this .delegate;
0315:                this .delegate = delegate;
0316:                support.firePropertyChange("delegate",
0317:                        new Boolean(oldDelegate), new Boolean(this .delegate));
0318:
0319:            }
0320:
0321:            /**
0322:             * Return descriptive information about this Loader implementation and
0323:             * the corresponding version number, in the format
0324:             * <code>&lt;description&gt;/&lt;version&gt;</code>.
0325:             */
0326:            public String getInfo() {
0327:
0328:                return (info);
0329:
0330:            }
0331:
0332:            /**
0333:             * Return the ClassLoader class name.
0334:             */
0335:            public String getLoaderClass() {
0336:
0337:                return (this .loaderClass);
0338:
0339:            }
0340:
0341:            /**
0342:             * Set the ClassLoader class name.
0343:             *
0344:             * @param loaderClass The new ClassLoader class name
0345:             */
0346:            public void setLoaderClass(String loaderClass) {
0347:
0348:                this .loaderClass = loaderClass;
0349:
0350:            }
0351:
0352:            /**
0353:             * Return the reloadable flag for this Loader.
0354:             */
0355:            public boolean getReloadable() {
0356:
0357:                return (this .reloadable);
0358:
0359:            }
0360:
0361:            /**
0362:             * Set the reloadable flag for this Loader.
0363:             *
0364:             * @param reloadable The new reloadable flag
0365:             */
0366:            public void setReloadable(boolean reloadable) {
0367:
0368:                // Process this property change
0369:                boolean oldReloadable = this .reloadable;
0370:                this .reloadable = reloadable;
0371:                support.firePropertyChange("reloadable", new Boolean(
0372:                        oldReloadable), new Boolean(this .reloadable));
0373:
0374:            }
0375:
0376:            // --------------------------------------------------------- Public Methods
0377:
0378:            /**
0379:             * Add a property change listener to this component.
0380:             *
0381:             * @param listener The listener to add
0382:             */
0383:            public void addPropertyChangeListener(
0384:                    PropertyChangeListener listener) {
0385:
0386:                support.addPropertyChangeListener(listener);
0387:
0388:            }
0389:
0390:            /**
0391:             * Add a new repository to the set of repositories for this class loader.
0392:             *
0393:             * @param repository Repository to be added
0394:             */
0395:            public void addRepository(String repository) {
0396:
0397:                if (log.isDebugEnabled())
0398:                    log.debug(sm.getString("webappLoader.addRepository",
0399:                            repository));
0400:
0401:                for (int i = 0; i < repositories.length; i++) {
0402:                    if (repository.equals(repositories[i]))
0403:                        return;
0404:                }
0405:                String results[] = new String[repositories.length + 1];
0406:                for (int i = 0; i < repositories.length; i++)
0407:                    results[i] = repositories[i];
0408:                results[repositories.length] = repository;
0409:                repositories = results;
0410:
0411:                if (started && (classLoader != null)) {
0412:                    classLoader.addRepository(repository);
0413:                    if (loaderRepositories != null)
0414:                        loaderRepositories.add(repository);
0415:                    setClassPath();
0416:                }
0417:
0418:            }
0419:
0420:            /**
0421:             * Return the set of repositories defined for this class loader.
0422:             * If none are defined, a zero-length array is returned.
0423:             * For security reason, returns a clone of the Array (since 
0424:             * String are immutable).
0425:             */
0426:            public String[] findRepositories() {
0427:
0428:                return ((String[]) repositories.clone());
0429:
0430:            }
0431:
0432:            public String[] getRepositories() {
0433:                return ((String[]) repositories.clone());
0434:            }
0435:
0436:            /** Extra repositories for this loader
0437:             */
0438:            public String getRepositoriesString() {
0439:                StringBuffer sb = new StringBuffer();
0440:                for (int i = 0; i < repositories.length; i++) {
0441:                    sb.append(repositories[i]).append(":");
0442:                }
0443:                return sb.toString();
0444:            }
0445:
0446:            public String[] getLoaderRepositories() {
0447:                if (loaderRepositories == null)
0448:                    return null;
0449:                String res[] = new String[loaderRepositories.size()];
0450:                loaderRepositories.toArray(res);
0451:                return res;
0452:            }
0453:
0454:            public String getLoaderRepositoriesString() {
0455:                String repositories[] = getLoaderRepositories();
0456:                StringBuffer sb = new StringBuffer();
0457:                for (int i = 0; i < repositories.length; i++) {
0458:                    sb.append(repositories[i]).append(":");
0459:                }
0460:                return sb.toString();
0461:            }
0462:
0463:            /** 
0464:             * Classpath, as set in org.apache.catalina.jsp_classpath context
0465:             * property
0466:             *
0467:             * @return The classpath
0468:             */
0469:            public String getClasspath() {
0470:                return classpath;
0471:            }
0472:
0473:            /**
0474:             * Has the internal repository associated with this Loader been modified,
0475:             * such that the loaded classes should be reloaded?
0476:             */
0477:            public boolean modified() {
0478:
0479:                return (classLoader.modified());
0480:
0481:            }
0482:
0483:            /**
0484:             * Used to periodically signal to the classloader to release JAR resources.
0485:             */
0486:            public void closeJARs(boolean force) {
0487:                if (classLoader != null) {
0488:                    classLoader.closeJARs(force);
0489:                }
0490:            }
0491:
0492:            /**
0493:             * Remove a property change listener from this component.
0494:             *
0495:             * @param listener The listener to remove
0496:             */
0497:            public void removePropertyChangeListener(
0498:                    PropertyChangeListener listener) {
0499:
0500:                support.removePropertyChangeListener(listener);
0501:
0502:            }
0503:
0504:            /**
0505:             * Return a String representation of this component.
0506:             */
0507:            public String toString() {
0508:
0509:                StringBuffer sb = new StringBuffer("WebappLoader[");
0510:                if (container != null)
0511:                    sb.append(container.getName());
0512:                sb.append("]");
0513:                return (sb.toString());
0514:
0515:            }
0516:
0517:            // ------------------------------------------------------ Lifecycle Methods
0518:
0519:            /**
0520:             * Add a lifecycle event listener to this component.
0521:             *
0522:             * @param listener The listener to add
0523:             */
0524:            public void addLifecycleListener(LifecycleListener listener) {
0525:
0526:                lifecycle.addLifecycleListener(listener);
0527:
0528:            }
0529:
0530:            /**
0531:             * Get the lifecycle listeners associated with this lifecycle. If this 
0532:             * Lifecycle has no listeners registered, a zero-length array is returned.
0533:             */
0534:            public LifecycleListener[] findLifecycleListeners() {
0535:
0536:                return lifecycle.findLifecycleListeners();
0537:
0538:            }
0539:
0540:            /**
0541:             * Remove a lifecycle event listener from this component.
0542:             *
0543:             * @param listener The listener to remove
0544:             */
0545:            public void removeLifecycleListener(LifecycleListener listener) {
0546:
0547:                lifecycle.removeLifecycleListener(listener);
0548:
0549:            }
0550:
0551:            private boolean initialized = false;
0552:
0553:            public void init() {
0554:                initialized = true;
0555:
0556:                if (oname == null) {
0557:                    // not registered yet - standalone or API
0558:                    if (container instanceof  StandardContext) {
0559:                        // Register ourself. The container must be a webapp
0560:                        try {
0561:                            StandardContext ctx = (StandardContext) container;
0562:                            Engine eng = (Engine) ctx.getParent().getParent();
0563:                            String path = ctx.getPath();
0564:                            if (path.equals("")) {
0565:                                path = "/";
0566:                            }
0567:                            oname = new ObjectName(ctx.getEngineName()
0568:                                    + ":type=Loader,path=" + path + ",host="
0569:                                    + ctx.getParent().getName());
0570:                            Registry.getRegistry(null, null).registerComponent(
0571:                                    this , oname, null);
0572:                            controller = oname;
0573:                        } catch (Exception e) {
0574:                            log.error("Error registering loader", e);
0575:                        }
0576:                    }
0577:                }
0578:
0579:                if (container == null) {
0580:                    // JMX created the loader
0581:                    // TODO
0582:
0583:                }
0584:            }
0585:
0586:            public void destroy() {
0587:                if (controller == oname) {
0588:                    // Self-registration, undo it
0589:                    Registry.getRegistry(null, null).unregisterComponent(oname);
0590:                    oname = null;
0591:                }
0592:                initialized = false;
0593:
0594:            }
0595:
0596:            /**
0597:             * Start this component, initializing our associated class loader.
0598:             *
0599:             * @exception LifecycleException if a lifecycle error occurs
0600:             */
0601:            public void start() throws LifecycleException {
0602:                // Validate and update our current component state
0603:                if (!initialized)
0604:                    init();
0605:                if (started)
0606:                    throw new LifecycleException(sm
0607:                            .getString("webappLoader.alreadyStarted"));
0608:                if (log.isDebugEnabled())
0609:                    log.debug(sm.getString("webappLoader.starting"));
0610:                lifecycle.fireLifecycleEvent(START_EVENT, null);
0611:                started = true;
0612:
0613:                if (container.getResources() == null) {
0614:                    log.info("No resources for " + container);
0615:                    return;
0616:                }
0617:                // Register a stream handler factory for the JNDI protocol
0618:                URLStreamHandlerFactory streamHandlerFactory = new DirContextURLStreamHandlerFactory();
0619:                if (first) {
0620:                    first = false;
0621:                    try {
0622:                        URL.setURLStreamHandlerFactory(streamHandlerFactory);
0623:                    } catch (Exception e) {
0624:                        // Log and continue anyway, this is not critical
0625:                        log.error("Error registering jndi stream handler", e);
0626:                    } catch (Throwable t) {
0627:                        // This is likely a dual registration
0628:                        log.info("Dual registration of jndi stream handler: "
0629:                                + t.getMessage());
0630:                    }
0631:                }
0632:
0633:                // Construct a class loader based on our current repositories list
0634:                try {
0635:
0636:                    classLoader = createClassLoader();
0637:                    classLoader.setResources(container.getResources());
0638:                    classLoader.setDebug(this .debug);
0639:                    classLoader.setDelegate(this .delegate);
0640:
0641:                    for (int i = 0; i < repositories.length; i++) {
0642:                        classLoader.addRepository(repositories[i]);
0643:                    }
0644:
0645:                    // Configure our repositories
0646:                    setRepositories();
0647:                    setClassPath();
0648:
0649:                    setPermissions();
0650:
0651:                    if (classLoader instanceof  Lifecycle)
0652:                        ((Lifecycle) classLoader).start();
0653:
0654:                    // Binding the Webapp class loader to the directory context
0655:                    DirContextURLStreamHandler.bind((ClassLoader) classLoader,
0656:                            this .container.getResources());
0657:
0658:                    StandardContext ctx = (StandardContext) container;
0659:                    Engine eng = (Engine) ctx.getParent().getParent();
0660:                    String path = ctx.getPath();
0661:                    if (path.equals("")) {
0662:                        path = "/";
0663:                    }
0664:                    ObjectName cloname = new ObjectName(ctx.getEngineName()
0665:                            + ":type=WebappClassLoader,path=" + path + ",host="
0666:                            + ctx.getParent().getName());
0667:                    Registry.getRegistry(null, null).registerComponent(
0668:                            classLoader, cloname, null);
0669:
0670:                } catch (Throwable t) {
0671:                    log.error("LifecycleException ", t);
0672:                    throw new LifecycleException("start: ", t);
0673:                }
0674:
0675:            }
0676:
0677:            /**
0678:             * Stop this component, finalizing our associated class loader.
0679:             *
0680:             * @exception LifecycleException if a lifecycle error occurs
0681:             */
0682:            public void stop() throws LifecycleException {
0683:
0684:                // Validate and update our current component state
0685:                if (!started)
0686:                    throw new LifecycleException(sm
0687:                            .getString("webappLoader.notStarted"));
0688:                if (log.isDebugEnabled())
0689:                    log.debug(sm.getString("webappLoader.stopping"));
0690:                lifecycle.fireLifecycleEvent(STOP_EVENT, null);
0691:                started = false;
0692:
0693:                // Remove context attributes as appropriate
0694:                if (container instanceof  Context) {
0695:                    ServletContext servletContext = ((Context) container)
0696:                            .getServletContext();
0697:                    servletContext.removeAttribute(Globals.CLASS_PATH_ATTR);
0698:                }
0699:
0700:                // Throw away our current class loader
0701:                if (classLoader instanceof  Lifecycle)
0702:                    ((Lifecycle) classLoader).stop();
0703:                DirContextURLStreamHandler.unbind((ClassLoader) classLoader);
0704:
0705:                try {
0706:                    StandardContext ctx = (StandardContext) container;
0707:                    Engine eng = (Engine) ctx.getParent().getParent();
0708:                    String path = ctx.getPath();
0709:                    if (path.equals("")) {
0710:                        path = "/";
0711:                    }
0712:                    ObjectName cloname = new ObjectName(ctx.getEngineName()
0713:                            + ":type=WebappClassLoader,path=" + path + ",host="
0714:                            + ctx.getParent().getName());
0715:                    Registry.getRegistry(null, null).unregisterComponent(
0716:                            cloname);
0717:                } catch (Throwable t) {
0718:                    log.error("LifecycleException ", t);
0719:                }
0720:
0721:                classLoader = null;
0722:
0723:                destroy();
0724:
0725:            }
0726:
0727:            // ----------------------------------------- PropertyChangeListener Methods
0728:
0729:            /**
0730:             * Process property change events from our associated Context.
0731:             *
0732:             * @param event The property change event that has occurred
0733:             */
0734:            public void propertyChange(PropertyChangeEvent event) {
0735:
0736:                // Validate the source of this event
0737:                if (!(event.getSource() instanceof  Context))
0738:                    return;
0739:                Context context = (Context) event.getSource();
0740:
0741:                // Process a relevant property change
0742:                if (event.getPropertyName().equals("reloadable")) {
0743:                    try {
0744:                        setReloadable(((Boolean) event.getNewValue())
0745:                                .booleanValue());
0746:                    } catch (NumberFormatException e) {
0747:                        log.error(sm.getString("webappLoader.reloadable", event
0748:                                .getNewValue().toString()));
0749:                    }
0750:                }
0751:
0752:            }
0753:
0754:            // ------------------------------------------------------- Private Methods
0755:
0756:            /**
0757:             * Create associated classLoader.
0758:             */
0759:            private WebappClassLoader createClassLoader() throws Exception {
0760:
0761:                Class clazz = Class.forName(loaderClass);
0762:                WebappClassLoader classLoader = null;
0763:
0764:                if (parentClassLoader == null) {
0765:                    parentClassLoader = Thread.currentThread()
0766:                            .getContextClassLoader();
0767:                }
0768:                Class[] argTypes = { ClassLoader.class };
0769:                Object[] args = { parentClassLoader };
0770:                Constructor constr = clazz.getConstructor(argTypes);
0771:                classLoader = (WebappClassLoader) constr.newInstance(args);
0772:
0773:                return classLoader;
0774:
0775:            }
0776:
0777:            /**
0778:             * Log a message on the Logger associated with our Container (if any)
0779:             *
0780:             * @param message Message to be logged
0781:             */
0782:            private void log(String message) {
0783:
0784:                Logger logger = null;
0785:                if (container != null)
0786:                    logger = container.getLogger();
0787:                if (logger != null)
0788:                    logger.log("WebappLoader[" + container.getName() + "]: "
0789:                            + message);
0790:                else {
0791:                    String containerName = null;
0792:                    if (container != null)
0793:                        containerName = container.getName();
0794:                    System.out.println("WebappLoader[" + containerName + "]: "
0795:                            + message);
0796:                }
0797:
0798:            }
0799:
0800:            /**
0801:             * Log a message on the Logger associated with our Container (if any)
0802:             *
0803:             * @param message Message to be logged
0804:             * @param throwable Associated exception
0805:             */
0806:            private void log(String message, Throwable throwable) {
0807:
0808:                Logger logger = null;
0809:                if (container != null)
0810:                    logger = container.getLogger();
0811:                if (logger != null) {
0812:                    logger.log("WebappLoader[" + container.getName() + "] "
0813:                            + message, throwable);
0814:                } else {
0815:                    String containerName = null;
0816:                    if (container != null)
0817:                        containerName = container.getName();
0818:                    System.out.println("WebappLoader[" + containerName + "]: "
0819:                            + message);
0820:                    System.out.println("" + throwable);
0821:                    throwable.printStackTrace(System.out);
0822:                }
0823:
0824:            }
0825:
0826:            /**
0827:             * Configure associated class loader permissions.
0828:             */
0829:            private void setPermissions() {
0830:
0831:                if (System.getSecurityManager() == null)
0832:                    return;
0833:                if (!(container instanceof  Context))
0834:                    return;
0835:
0836:                // Tell the class loader the root of the context
0837:                ServletContext servletContext = ((Context) container)
0838:                        .getServletContext();
0839:
0840:                // Assigning permissions for the work directory
0841:                File workDir = (File) servletContext
0842:                        .getAttribute(Globals.WORK_DIR_ATTR);
0843:                if (workDir != null) {
0844:                    try {
0845:                        String workDirPath = workDir.getCanonicalPath();
0846:                        classLoader.addPermission(new FilePermission(
0847:                                workDirPath, "read,write"));
0848:                        classLoader.addPermission(new FilePermission(
0849:                                workDirPath + File.separator + "-",
0850:                                "read,write,delete"));
0851:                    } catch (IOException e) {
0852:                        // Ignore
0853:                    }
0854:                }
0855:
0856:                try {
0857:
0858:                    URL rootURL = servletContext.getResource("/");
0859:                    classLoader.addPermission(rootURL);
0860:
0861:                    String contextRoot = servletContext.getRealPath("/");
0862:                    if (contextRoot != null) {
0863:                        try {
0864:                            contextRoot = (new File(contextRoot))
0865:                                    .getCanonicalPath();
0866:                            classLoader.addPermission(contextRoot);
0867:                        } catch (IOException e) {
0868:                            // Ignore
0869:                        }
0870:                    }
0871:
0872:                    URL classesURL = servletContext
0873:                            .getResource("/WEB-INF/classes/");
0874:                    classLoader.addPermission(classesURL);
0875:                    URL libURL = servletContext.getResource("/WEB-INF/lib/");
0876:                    classLoader.addPermission(libURL);
0877:
0878:                    if (contextRoot != null) {
0879:
0880:                        if (libURL != null) {
0881:                            File rootDir = new File(contextRoot);
0882:                            File libDir = new File(rootDir, "WEB-INF/lib/");
0883:                            try {
0884:                                String path = libDir.getCanonicalPath();
0885:                                classLoader.addPermission(path);
0886:                            } catch (IOException e) {
0887:                            }
0888:                        }
0889:
0890:                    } else {
0891:
0892:                        if (workDir != null) {
0893:                            if (libURL != null) {
0894:                                File libDir = new File(workDir, "WEB-INF/lib/");
0895:                                try {
0896:                                    String path = libDir.getCanonicalPath();
0897:                                    classLoader.addPermission(path);
0898:                                } catch (IOException e) {
0899:                                }
0900:                            }
0901:                            if (classesURL != null) {
0902:                                File classesDir = new File(workDir,
0903:                                        "WEB-INF/classes/");
0904:                                try {
0905:                                    String path = classesDir.getCanonicalPath();
0906:                                    classLoader.addPermission(path);
0907:                                } catch (IOException e) {
0908:                                }
0909:                            }
0910:                        }
0911:
0912:                    }
0913:
0914:                } catch (MalformedURLException e) {
0915:                }
0916:
0917:            }
0918:
0919:            /**
0920:             * Configure the repositories for our class loader, based on the
0921:             * associated Context.
0922:             */
0923:            private void setRepositories() {
0924:
0925:        if (!(container instanceof  Context))
0926:            return;
0927:        ServletContext servletContext =
0928:            ((Context) container).getServletContext();
0929:        if (servletContext == null)
0930:            return;
0931:
0932:        loaderRepositories=new ArrayList();
0933:        // Loading the work directory
0934:        File workDir =
0935:            (File) servletContext.getAttribute(Globals.WORK_DIR_ATTR);
0936:        if (workDir == null) {
0937:            log.info("No work dir for " + servletContext);
0938:        }
0939:
0940:        if( log.isDebugEnabled()) 
0941:            log.debug(sm.getString("webappLoader.deploy", workDir.getAbsolutePath()));
0942:
0943:        classLoader.setWorkDir(workDir);
0944:
0945:        DirContext resources = container.getResources();
0946:
0947:        // Setting up the class repository (/WEB-INF/classes), if it exists
0948:
0949:        String classesPath = "/WEB-INF/classes";
0950:        DirContext classes = null;
0951:
0952:        try {
0953:            Object object = resources.lookup(classesPath);
0954:            if (object instanceof  DirContext) {
0955:                classes = (DirContext) object;
0956:            }
0957:        } catch(NamingException e) {
0958:            // Silent catch: it's valid that no /WEB-INF/classes collection
0959:            // exists
0960:        }
0961:
0962:        if (classes != null) {
0963:
0964:            File classRepository = null;
0965:
0966:            String absoluteClassesPath =
0967:                servletContext.getRealPath(classesPath);
0968:
0969:            if (absoluteClassesPath != null) {
0970:
0971:                classRepository = new File(absoluteClassesPath);
0972:
0973:            } else {
0974:
0975:                classRepository = new File(workDir, classesPath);
0976:                classRepository.mkdirs();
0977:                copyDir(classes, classRepository);
0978:
0979:            }
0980:
0981:            if(log.isDebugEnabled())
0982:                log.debug(sm.getString("webappLoader.classDeploy", classesPath,
0983:                             classRepository.getAbsolutePath()));
0984:
0985:
0986:            // Adding the repository to the class loader
0987:            classLoader.addRepository(classesPath + "/", classRepository);
0988:            loaderRepositories.add(classesPath + "/" );
0989:
0990:        }
0991:
0992:        // Setting up the JAR repository (/WEB-INF/lib), if it exists
0993:
0994:        String libPath = "/WEB-INF/lib";
0995:
0996:        classLoader.setJarPath(libPath);
0997:
0998:        DirContext libDir = null;
0999:        // Looking up directory /WEB-INF/lib in the context
1000:        try {
1001:            Object object = resources.lookup(libPath);
1002:            if (object instanceof  DirContext)
1003:                libDir = (DirContext) object;
1004:        } catch(NamingException e) {
1005:            // Silent catch: it's valid that no /WEB-INF/lib collection
1006:            // exists
1007:        }
1008:
1009:        if (libDir != null) {
1010:
1011:            boolean copyJars = false;
1012:            String absoluteLibPath = servletContext.getRealPath(libPath);
1013:
1014:            File destDir = null;
1015:
1016:            if (absoluteLibPath != null) {
1017:                destDir = new File(absoluteLibPath);
1018:            } else {
1019:                copyJars = true;
1020:                destDir = new File(workDir, libPath);
1021:                destDir.mkdirs();
1022:            }
1023:
1024:            // Looking up directory /WEB-INF/lib in the context
1025:            try {
1026:                NamingEnumeration enum = resources.listBindings(libPath);
1027:                while (enum.hasMoreElements()) {
1028:
1029:                    Binding binding = (Binding) enum.nextElement();
1030:                    String filename = libPath + "/" + binding.getName();
1031:                    if (!filename.endsWith(".jar"))
1032:                        continue;
1033:
1034:                    // Copy JAR in the work directory, always (the JAR file
1035:                    // would get locked otherwise, which would make it
1036:                    // impossible to update it or remove it at runtime)
1037:                    File destFile = new File(destDir, binding.getName());
1038:
1039:                    if( log.isDebugEnabled())
1040:                    log.debug(sm.getString("webappLoader.jarDeploy", filename,
1041:                                     destFile.getAbsolutePath()));
1042:
1043:                    Resource jarResource = (Resource) binding.getObject();
1044:                    if (copyJars) {
1045:                        if (!copy(jarResource.streamContent(),
1046:                                  new FileOutputStream(destFile)))
1047:                            continue;
1048:                    }
1049:
1050:                    try {
1051:                        JarFile jarFile = new JarFile(destFile);
1052:                        classLoader.addJar(filename, jarFile, destFile);
1053:                    } catch (Exception ex) {
1054:                        // Catch the exception if there is an empty jar file
1055:                        // Should ignore and continute loading other jar files 
1056:                        // in the dir
1057:                    }
1058:                    
1059:                    loaderRepositories.add( filename );
1060:
1061:                }
1062:            } catch (NamingException e) {
1063:                // Silent catch: it's valid that no /WEB-INF/lib directory
1064:                // exists
1065:            } catch (IOException e) {
1066:                e.printStackTrace();
1067:            }
1068:
1069:        }
1070:
1071:    }
1072:
1073:            /**
1074:             * Set the appropriate context attribute for our class path.  This
1075:             * is required only because Jasper depends on it.
1076:             */
1077:            private void setClassPath() {
1078:
1079:                // Validate our current state information
1080:                if (!(container instanceof  Context))
1081:                    return;
1082:                ServletContext servletContext = ((Context) container)
1083:                        .getServletContext();
1084:                if (servletContext == null)
1085:                    return;
1086:
1087:                if (container instanceof  StandardContext) {
1088:                    String baseClasspath = ((StandardContext) container)
1089:                            .getCompilerClasspath();
1090:                    if (baseClasspath != null) {
1091:                        servletContext.setAttribute(Globals.CLASS_PATH_ATTR,
1092:                                baseClasspath);
1093:                        return;
1094:                    }
1095:                }
1096:
1097:                StringBuffer classpath = new StringBuffer();
1098:
1099:                // Assemble the class path information from our class loader chain
1100:                ClassLoader loader = getClassLoader();
1101:                int layers = 0;
1102:                int n = 0;
1103:                while (loader != null) {
1104:                    if (!(loader instanceof  URLClassLoader)) {
1105:                        String cp = getClasspath(loader);
1106:                        if (cp == null) {
1107:                            log.info("Unknown loader " + loader + " "
1108:                                    + loader.getClass());
1109:                            break;
1110:                        } else {
1111:                            if (n > 0)
1112:                                classpath.append(File.pathSeparator);
1113:                            classpath.append(cp);
1114:                            n++;
1115:                        }
1116:                        break;
1117:                        //continue;
1118:                    }
1119:                    URL repositories[] = ((URLClassLoader) loader).getURLs();
1120:                    for (int i = 0; i < repositories.length; i++) {
1121:                        String repository = repositories[i].toString();
1122:                        if (repository.startsWith("file://"))
1123:                            repository = repository.substring(7);
1124:                        else if (repository.startsWith("file:"))
1125:                            repository = repository.substring(5);
1126:                        else if (repository.startsWith("jndi:"))
1127:                            repository = servletContext.getRealPath(repository
1128:                                    .substring(5));
1129:                        else
1130:                            continue;
1131:                        if (repository == null)
1132:                            continue;
1133:                        if (n > 0)
1134:                            classpath.append(File.pathSeparator);
1135:                        classpath.append(repository);
1136:                        n++;
1137:                    }
1138:                    loader = loader.getParent();
1139:                    layers++;
1140:                }
1141:
1142:                this .classpath = classpath.toString();
1143:
1144:                // Store the assembled class path as a servlet context attribute
1145:                servletContext.setAttribute(Globals.CLASS_PATH_ATTR, classpath
1146:                        .toString());
1147:
1148:            }
1149:
1150:            // try to extract the classpath from a loader that is not URLClassLoader
1151:            private String getClasspath(ClassLoader loader) {
1152:                try {
1153:                    Method m = loader.getClass().getMethod("getClasspath",
1154:                            new Class[] {});
1155:                    if (log.isTraceEnabled())
1156:                        log.trace("getClasspath " + m);
1157:                    if (m == null)
1158:                        return null;
1159:                    Object o = m.invoke(loader, new Object[] {});
1160:                    if (log.isDebugEnabled())
1161:                        log.debug("gotClasspath " + o);
1162:                    if (o instanceof  String)
1163:                        return (String) o;
1164:                    return null;
1165:                } catch (Exception ex) {
1166:                    if (log.isDebugEnabled())
1167:                        log.debug("getClasspath ", ex);
1168:                }
1169:                return null;
1170:            }
1171:
1172:            /**
1173:             * Copy directory.
1174:             */
1175:            private boolean copyDir(DirContext srcDir, File destDir) {
1176:
1177:        try {
1178:
1179:            NamingEnumeration enum = srcDir.list("");
1180:            while (enum.hasMoreElements()) {
1181:                NameClassPair ncPair =
1182:                    (NameClassPair) enum.nextElement();
1183:                String name = ncPair.getName();
1184:                Object object = srcDir.lookup(name);
1185:                File currentFile = new File(destDir, name);
1186:                if (object instanceof  Resource) {
1187:                    InputStream is = ((Resource) object).streamContent();
1188:                    OutputStream os = new FileOutputStream(currentFile);
1189:                    if (!copy(is, os))
1190:                        return false;
1191:                } else if (object instanceof  InputStream) {
1192:                    OutputStream os = new FileOutputStream(currentFile);
1193:                    if (!copy((InputStream) object, os))
1194:                        return false;
1195:                } else if (object instanceof  DirContext) {
1196:                    currentFile.mkdir();
1197:                    copyDir((DirContext) object, currentFile);
1198:                }
1199:            }
1200:
1201:        } catch (NamingException e) {
1202:            return false;
1203:        } catch (IOException e) {
1204:            return false;
1205:        }
1206:
1207:        return true;
1208:
1209:    }
1210:
1211:            /**
1212:             * Copy a file to the specified temp directory. This is required only
1213:             * because Jasper depends on it.
1214:             */
1215:            private boolean copy(InputStream is, OutputStream os) {
1216:
1217:                try {
1218:                    byte[] buf = new byte[4096];
1219:                    while (true) {
1220:                        int len = is.read(buf);
1221:                        if (len < 0)
1222:                            break;
1223:                        os.write(buf, 0, len);
1224:                    }
1225:                    is.close();
1226:                    os.close();
1227:                } catch (IOException e) {
1228:                    return false;
1229:                }
1230:
1231:                return true;
1232:
1233:            }
1234:
1235:            private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
1236:                    .getLog(WebappLoader.class);
1237:
1238:            private ObjectName oname;
1239:            private MBeanServer mserver;
1240:            private String domain;
1241:            private ObjectName controller;
1242:
1243:            public ObjectName preRegister(MBeanServer server, ObjectName name)
1244:                    throws Exception {
1245:                oname = name;
1246:                mserver = server;
1247:                domain = name.getDomain();
1248:
1249:                return name;
1250:            }
1251:
1252:            public void postRegister(Boolean registrationDone) {
1253:            }
1254:
1255:            public void preDeregister() throws Exception {
1256:            }
1257:
1258:            public void postDeregister() {
1259:            }
1260:
1261:            public ObjectName getController() {
1262:                return controller;
1263:            }
1264:
1265:            public void setController(ObjectName controller) {
1266:                this.controller = controller;
1267:            }
1268:
1269:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.