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