Source Code Cross Referenced for WebappLoader.java in  » Sevlet-Container » apache-tomcat-6.0.14 » 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 » apache tomcat 6.0.14 » org.apache.catalina.loader 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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