[Tomcat6.0源码]项目的部署

来源:互联网 发布:北京美特软件 编辑:程序博客网 时间:2024/05/16 06:17

上回说到在HostConfig.start()会部署所有的项目:

    public void start() {        if (log.isDebugEnabled())            log.debug(sm.getString("hostConfig.start"));        try {            ObjectName hostON = new ObjectName(host.getObjectName());            oname = new ObjectName                (hostON.getDomain() + ":type=Deployer,host=" + host.getName());            Registry.getRegistry(null, null).registerComponent                (this, oname, this.getClass().getName());        } catch (Exception e) {            log.error(sm.getString("hostConfig.jmx.register", oname), e);        }        if (host.getDeployOnStartup())            deployApps();            }

HostConfig.deployApps():

    /**     * Deploy applications for any directories or WAR files that are found     * in our "application root" directory.     */    protected void deployApps() {        File appBase = appBase();//webapps        File configBase = configBase();//conf/Catalina/localhost        String[] filteredAppPaths = filterAppPaths(appBase.list());        // Deploy XML descriptors from configBase        deployDescriptors(configBase, configBase.list());        // Deploy WARs, and loop if additional descriptors are found        deployWARs(appBase, filteredAppPaths);        // Deploy expanded folders        deployDirectories(appBase, filteredAppPaths);            }

HostConfig.deployDescriptors();是部署文件夹项目,deployWARs是部署war包的项目,主要过程一样,以HostConfig.deployWARs()为例:

    protected void deployWARs(File appBase, String[] files) {                if (files == null)            return;                for (int i = 0; i < files.length; i++) {                        if (files[i].equalsIgnoreCase("META-INF"))                continue;            if (files[i].equalsIgnoreCase("WEB-INF"))                continue;            File dir = new File(appBase, files[i]);            if (files[i].toLowerCase().endsWith(".war") && dir.isFile()                    && !invalidWars.contains(files[i]) ) {                                // Calculate the context path and make sure it is unique                String contextPath = "/" + files[i].replace('#','/');                int period = contextPath.lastIndexOf(".");                contextPath = contextPath.substring(0, period);                                // Check for WARs with /../ /./ or similar sequences in the name                if (!validateContextPath(appBase, contextPath)) {                    log.error(sm.getString(                            "hostConfig.illegalWarName", files[i]));                    invalidWars.add(files[i]);                    continue;                }                if (contextPath.equals("/ROOT"))                    contextPath = "";                                if (isServiced(contextPath))                    continue;                                String file = files[i];                                deployWAR(contextPath, dir, file);                            }                    }            }

HostConfig.deployWAR():

    protected void deployWAR(String contextPath, File war, String file) {                if (deploymentExists(contextPath))            return;                // Checking for a nested /META-INF/context.xml        JarFile jar = null;        JarEntry entry = null;        InputStream istream = null;        BufferedOutputStream ostream = null;        File xml = new File            (configBase, file.substring(0, file.lastIndexOf(".")) + ".xml");        if (deployXML && !xml.exists()) {            try {                jar = new JarFile(war);                entry = jar.getJarEntry(Constants.ApplicationContextXml);                if (entry != null) {                    istream = jar.getInputStream(entry);                                        configBase.mkdirs();                                        ostream =                        new BufferedOutputStream                        (new FileOutputStream(xml), 1024);                    byte buffer[] = new byte[1024];                    while (true) {                        int n = istream.read(buffer);                        if (n < 0) {                            break;                        }                        ostream.write(buffer, 0, n);                    }                    ostream.flush();                    ostream.close();                    ostream = null;                    istream.close();                    istream = null;                    entry = null;                    jar.close();                    jar = null;                }            } catch (Exception e) {                // Ignore and continue                if (ostream != null) {                    try {                        ostream.close();                    } catch (Throwable t) {                        ;                    }                    ostream = null;                }                if (istream != null) {                    try {                        istream.close();                    } catch (Throwable t) {                        ;                    }                    istream = null;                }            } finally {                entry = null;                if (jar != null) {                    try {                        jar.close();                    } catch (Throwable t) {                        ;                    }                    jar = null;                }            }        }                DeployedApplication deployedApp = new DeployedApplication(contextPath);                // Deploy the application in this WAR file        if(log.isInfoEnabled())             log.info(sm.getString("hostConfig.deployJar", file));        try {            Context context = null;            if (deployXML && xml.exists()) {                synchronized (digester) {                    try {                        context = (Context) digester.parse(xml);                        if (context == null) {                            log.error(sm.getString("hostConfig.deployDescriptor.error",                                    file));                            return;                        }                    } finally {                        digester.reset();                    }                }                context.setConfigFile(xml.getAbsolutePath());            } else {                context = (Context) Class.forName(contextClass).newInstance();            }            // Populate redeploy resources with the WAR file            deployedApp.redeployResources.put                (war.getAbsolutePath(), new Long(war.lastModified()));            if (deployXML && xml.exists()) {                deployedApp.redeployResources.put                (xml.getAbsolutePath(), new Long(xml.lastModified()));            }            if (context instanceof Lifecycle) {                Class clazz = Class.forName(host.getConfigClass());                LifecycleListener listener =                    (LifecycleListener) clazz.newInstance();                ((Lifecycle) context).addLifecycleListener(listener);            }            context.setPath(contextPath);            context.setDocBase(file);            host.addChild(context);            // If we're unpacking WARs, the docBase will be mutated after            // starting the context            if (unpackWARs && (context.getDocBase() != null)) {                String name = null;                String path = context.getPath();                if (path.equals("")) {                    name = "ROOT";                } else {                    if (path.startsWith("/")) {                        name = path.substring(1);                    } else {                        name = path;                    }                }                name = name.replace('/', '#');                File docBase = new File(name);                if (!docBase.isAbsolute()) {                    docBase = new File(appBase(), name);                }                deployedApp.redeployResources.put(docBase.getAbsolutePath(),                        new Long(docBase.lastModified()));                addWatchedResources(deployedApp, docBase.getAbsolutePath(), context);            } else {                addWatchedResources(deployedApp, null, context);            }        } catch (Throwable t) {            log.error(sm.getString("hostConfig.deployJar.error", file), t);        }                deployed.put(contextPath, deployedApp);    }

StandardHost.addChild():

   /**     * Add a child Container, only if the proposed child is an implementation     * of Context.     *     * @param child Child container to be added     */    public void addChild(Container child) {        if (child instanceof Lifecycle) {            ((Lifecycle) child).addLifecycleListener(                    new MemoryLeakTrackingListener());        }        if (!(child instanceof Context))            throw new IllegalArgumentException                (sm.getString("standardHost.notContext"));        super.addChild(child);    }

ContainerBase.addChild():

    public void addChild(Container child) {        if (Globals.IS_SECURITY_ENABLED) {            PrivilegedAction dp =                new PrivilegedAddChild(child);            AccessController.doPrivileged(dp);        } else {            addChildInternal(child);        }    }

ContainerBase.addChildInternal():

    private void addChildInternal(Container child) {        if( log.isDebugEnabled() )            log.debug("Add child " + child + " " + this);        synchronized(children) {            if (children.get(child.getName()) != null)                throw new IllegalArgumentException("addChild:  Child name '" +                                                   child.getName() +                                                   "' is not unique");            child.setParent(this);  // May throw IAE            children.put(child.getName(), child);            // Start child            if (started && startChildren && (child instanceof Lifecycle)) {                boolean success = false;                try {                    ((Lifecycle) child).start();                    success = true;                } catch (LifecycleException e) {                    log.error("ContainerBase.addChild: start: ", e);                    throw new IllegalStateException                        ("ContainerBase.addChild: start: " + e);                } finally {                    if (!success) {                        children.remove(child.getName());                    }                }            }            fireContainerEvent(ADD_CHILD_EVENT, child);        }    }

((Lifecycle) child).start();即StandardContext.start():

    public synchronized void start() throws LifecycleException {        //if (lazy ) return;        if (started) {            if(log.isInfoEnabled())                log.info(sm.getString("containerBase.alreadyStarted", logName()));            return;        }        if( !initialized ) {             try {                init();            } catch( Exception ex ) {                throw new LifecycleException("Error initializaing ", ex);            }        }        if(log.isDebugEnabled())            log.debug("Starting " + ("".equals(getName()) ? "ROOT" : getName()));        // Set JMX object name for proper pipeline registration        preRegisterJMX();        if ((oname != null) &&             (Registry.getRegistry(null, null).getMBeanServer().isRegistered(oname))) {            // As things depend on the JMX registration, the context            // must be reregistered again once properly initialized            Registry.getRegistry(null, null).unregisterComponent(oname);        }        // Notify our interested LifecycleListeners        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);        setAvailable(false);        setConfigured(false);        boolean ok = true;        // Add missing components as necessary        if (webappResources == null) {   // (1) Required by Loader            if (log.isDebugEnabled())                log.debug("Configuring default Resources");            try {                if ((docBase != null) && (docBase.endsWith(".war")) && (!(new File(getBasePath())).isDirectory()))                    setResources(new WARDirContext());                else                    setResources(new FileDirContext());            } catch (IllegalArgumentException e) {                log.error("Error initializing resources: " + e.getMessage());                ok = false;            }        }        if (ok) {            if (!resourcesStart()) {                log.error( "Error in resourceStart()");                ok = false;            }        }        // Look for a realm - that may have been configured earlier.         // If the realm is added after context - it'll set itself.        // TODO: what is the use case for this ?         if( realm == null && mserver != null ) {            ObjectName realmName=null;            try {                realmName=new ObjectName( getEngineName() + ":type=Realm,host=" +                         getHostname() + ",path=" + getPath());                if( mserver.isRegistered(realmName ) ) {                    mserver.invoke(realmName, "init",                             new Object[] {},                            new String[] {}                    );                            }            } catch( Throwable t ) {                if(log.isDebugEnabled())                    log.debug("No realm for this host " + realmName);            }        }                if (getLoader() == null) {            WebappLoader webappLoader = new WebappLoader(getParentClassLoader());            webappLoader.setDelegate(getDelegate());            setLoader(webappLoader);        }        // Initialize character set mapper        getCharsetMapper();        // Post work directory        postWorkDirectory();        // Validate required extensions        boolean dependencyCheck = true;        try {            dependencyCheck = ExtensionValidator.validateApplication                (getResources(), this);        } catch (IOException ioe) {            log.error("Error in dependencyCheck", ioe);            dependencyCheck = false;        }        if (!dependencyCheck) {            // do not make application available if depency check fails            ok = false;        }        // Reading the "catalina.useNaming" environment variable        String useNamingProperty = System.getProperty("catalina.useNaming");        if ((useNamingProperty != null)            && (useNamingProperty.equals("false"))) {            useNaming = false;        }        if (ok && isUseNaming()) {            if (namingContextListener == null) {                namingContextListener = new NamingContextListener();                namingContextListener.setName(getNamingContextName());                addLifecycleListener(namingContextListener);            }        }                // Standard container startup        if (log.isDebugEnabled())            log.debug("Processing standard container startup");                // Binding thread        ClassLoader oldCCL = bindThread();        boolean mainOk = false;        try {            if (ok) {                                started = true;                // Start our subordinate components, if any                if ((loader != null) && (loader instanceof Lifecycle))                    ((Lifecycle) loader).start();                // since the loader just started, the webapp classloader is now                // created.                // By calling unbindThread and bindThread in a row, we setup the                // current Thread CCL to be the webapp classloader                unbindThread(oldCCL);                oldCCL = bindThread();                // Initialize logger again. Other components might have used it too early,                 // so it should be reset.                logger = null;                getLogger();                if ((logger != null) && (logger instanceof Lifecycle))                    ((Lifecycle) logger).start();                                if ((cluster != null) && (cluster instanceof Lifecycle))                    ((Lifecycle) cluster).start();                if ((realm != null) && (realm instanceof Lifecycle))                    ((Lifecycle) realm).start();                if ((resources != null) && (resources instanceof Lifecycle))                    ((Lifecycle) resources).start();                // Start our child containers, if any                Container children[] = findChildren();                for (int i = 0; i < children.length; i++) {                    if (children[i] instanceof Lifecycle)                        ((Lifecycle) children[i]).start();                }                // Start the Valves in our pipeline (including the basic),                // if any                if (pipeline instanceof Lifecycle) {                    ((Lifecycle) pipeline).start();                }                                // Notify our interested LifecycleListeners                lifecycle.fireLifecycleEvent(START_EVENT, null);                                // Acquire clustered manager                Manager contextManager = null;                if (manager == null) {                    if ( (getCluster() != null) && distributable) {                        try {                            contextManager = getCluster().createManager(getName());                        } catch (Exception ex) {                            log.error("standardContext.clusterFail", ex);                            ok = false;                        }                    } else {                        contextManager = new StandardManager();                    }                }                                 // Configure default manager if none was specified                if (contextManager != null) {                    setManager(contextManager);                }                if (manager!=null && (getCluster() != null) && distributable) {                    //let the cluster know that there is a context that is distributable                    //and that it has its own manager                    getCluster().registerManager(manager);                }                                mainOk = true;            }        } finally {            // Unbinding thread            unbindThread(oldCCL);            if (!mainOk) {                // An exception occurred                // Register with JMX anyway, to allow management                registerJMX();            }        }        if (!getConfigured()) {            log.error( "Error getConfigured");            ok = false;        }        // We put the resources into the servlet context        if (ok)            getServletContext().setAttribute                (Globals.RESOURCES_ATTR, getResources());        // Initialize associated mapper        mapper.setContext(getPath(), welcomeFiles, resources);        // Binding thread        oldCCL = bindThread();        // Set annotation processing parameter for Jasper (unfortunately, since        // this can be configured in many places and not just in /WEB-INF/web.xml,        // there are not many solutions)        // Initialize annotation processor        if (ok && !getIgnoreAnnotations()) {            if (annotationProcessor == null) {                if (isUseNaming() && namingContextListener != null) {                    annotationProcessor =                         new DefaultAnnotationProcessor(namingContextListener.getEnvContext());                } else {                    annotationProcessor = new DefaultAnnotationProcessor(null);                }            }            getServletContext().setAttribute                (AnnotationProcessor.class.getName(), annotationProcessor);        }        try {                        // Create context attributes that will be required            if (ok) {                postWelcomeFiles();            }                        // Set up the context init params            mergeParameters();            if (ok) {                // Notify our interested LifecycleListeners                lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);            }                        // Configure and call application event listeners            if (ok) {                if (!listenerStart()) {                    log.error( "Error listenerStart");                    ok = false;                }            }                        try {                // Start manager                if ((manager != null) && (manager instanceof Lifecycle)) {                    ((Lifecycle) getManager()).start();                }                    // Start ContainerBackgroundProcessor thread                super.threadStart();            } catch(Exception e) {                log.error("Error manager.start()", e);                ok = false;            }            // Configure and call application filters            if (ok) {                if (!filterStart()) {                    log.error( "Error filterStart");                    ok = false;                }            }                        // Load and initialize all "load on startup" servlets            if (ok) {                loadOnStartup(findChildren());            }                    } finally {            // Unbinding thread            unbindThread(oldCCL);        }        // Set available status depending upon startup success        if (ok) {            if (log.isDebugEnabled())                log.debug("Starting completed");            setAvailable(true);        } else {            log.error(sm.getString("standardContext.startFailed", getName()));            try {                stop();            } catch (Throwable t) {                log.error(sm.getString("standardContext.startCleanup"), t);            }            setAvailable(false);        }        // JMX registration        registerJMX();        startTime=System.currentTimeMillis();                // Send j2ee.state.running notification         if (ok && (this.getObjectName() != null)) {            Notification notification =                 new Notification("j2ee.state.running", this.getObjectName(),                                 sequenceNumber++);            broadcaster.sendNotification(notification);        }        // Close all JARs right away to avoid always opening a peak number         // of files on startup        if (getLoader() instanceof WebappLoader) {            ((WebappLoader) getLoader()).closeJARs(true);        }        // Reinitializing if something went wrong        if (!ok && started) {            stop();        }        //cacheContext();    }

StandardContext.init():

    public void init() throws Exception {        if( this.getParent() == null ) {            ObjectName parentName=getParentName();                        if( ! mserver.isRegistered(parentName)) {                if(log.isDebugEnabled())                    log.debug("No host, creating one " + parentName);                StandardHost host=new StandardHost();                host.setName(hostName);                host.setAutoDeploy(false);                Registry.getRegistry(null, null)                    .registerComponent(host, parentName, null);                // We could do it the hard way...                //mserver.invoke(parentName, "init", new Object[] {}, new String[] {} );                // or same thing easier:                host.init();            }                        // Add the main configuration listener            LifecycleListener config = null;            try {                String configClassName = null;                try {                    configClassName = String.valueOf(mserver.getAttribute(parentName, "configClass"));                } catch (AttributeNotFoundException e) {                    // Ignore, it's normal a host may not have this optional attribute                }                if (configClassName != null) {                    Class clazz = Class.forName(configClassName);                    config = (LifecycleListener) clazz.newInstance();                } else {                    config = new ContextConfig();                }            } catch (Exception e) {                log.warn("Error creating ContextConfig for " + parentName, e);                throw e;            }            this.addLifecycleListener(config);            if (log.isDebugEnabled()) {                log.debug("AddChild " + parentName + " " + this);            }            try {                mserver.invoke(parentName, "addChild", new Object[] { this },                        new String[] {"org.apache.catalina.Container"});            } catch (Exception e) {                destroy();                throw e;            }            // It's possible that addChild may have started us            if( initialized ) {                return;            }        }        if (processTlds) {            this.addLifecycleListener(new TldConfig());        }        super.init();                // Notify our interested LifecycleListeners        lifecycle.fireLifecycleEvent(INIT_EVENT, null);        // Send j2ee.state.starting notification         if (this.getObjectName() != null) {            Notification notification = new Notification("j2ee.state.starting",                                                         this.getObjectName(),                                                         sequenceNumber++);            broadcaster.sendNotification(notification);        }            }

lifecycle.fireLifecycleEvent(INIT_EVENT, null);LifecycleSupport.fireLifecycleEvent():

    /**     * Notify all lifecycle event listeners that a particular event has     * occurred for this Container.  The default implementation performs     * this notification synchronously using the calling thread.     *     * @param type Event type     * @param data Event data     */    public void fireLifecycleEvent(String type, Object data) {        if (Lifecycle.INIT_EVENT.equals(type)) {            state = "INITIALIZED";        } else if (Lifecycle.BEFORE_START_EVENT.equals(type)) {            state = "STARTING_PREP";        } else if (Lifecycle.START_EVENT.equals(type)) {            state = "STARTING";        } else if (Lifecycle.AFTER_START_EVENT.equals(type)) {            state = "STARTED";        } else if (Lifecycle.BEFORE_STOP_EVENT.equals(type)) {            state = "STOPPING_PREP";        } else if (Lifecycle.STOP_EVENT.equals(type)) {            state = "STOPPING";        } else if (Lifecycle.AFTER_STOP_EVENT.equals(type)) {            state = "STOPPED";        } else if (Lifecycle.DESTROY_EVENT.equals(type)) {            state = "DESTROYED";        }        LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);        LifecycleListener interested[] = listeners;        for (int i = 0; i < interested.length; i++)            interested[i].lifecycleEvent(event);    }

调用所有绑定的监听器的lifecycleEvent()方法,其中有ContextConfig.lifecycleEvent():

    public void lifecycleEvent(LifecycleEvent event) {        // Identify the context we are associated with        try {            context = (Context) event.getLifecycle();        } catch (ClassCastException e) {            log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e);            return;        }        // Process the event that has occurred        if (event.getType().equals(Lifecycle.START_EVENT)) {            start();        } else if (event.getType().equals(StandardContext.BEFORE_START_EVENT)) {            beforeStart();        } else if (event.getType().equals(StandardContext.AFTER_START_EVENT)) {            // Restore docBase for management tools            if (originalDocBase != null) {                String docBase = context.getDocBase();                context.setDocBase(originalDocBase);                originalDocBase = docBase;            }        } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {            if (originalDocBase != null) {                String docBase = context.getDocBase();                context.setDocBase(originalDocBase);                originalDocBase = docBase;            }            stop();        } else if (event.getType().equals(Lifecycle.INIT_EVENT)) {            init();        } else if (event.getType().equals(Lifecycle.DESTROY_EVENT)) {            destroy();        }    }

INIT_EVENT参数调用的是ContextConfig.init():

    protected void init() {        // Called from StandardContext.init()        if (webDigester == null){            webDigester = createWebDigester();            webDigester.getParser();        }                if (contextDigester == null){            contextDigester = createContextDigester();            contextDigester.getParser();        }        if (log.isDebugEnabled())            log.debug(sm.getString("contextConfig.init"));        context.setConfigured(false);        ok = true;                contextConfig();                try {            fixDocBase();        } catch (IOException e) {            log.error(sm.getString(                    "contextConfig.fixDocBase", context.getPath()), e);        }            }

先设置web.xml、context.xml的解析规则,处理默认的配置文件。

createWebDigester()里调用WebRuleSet.addRuleInstances():

digester.addCallMethod(prefix + "web-app/listener/listener-class",                                "addApplicationListener", 0);

Digester.addCallMethod()方法是解析到listenner-calss节点时,取其值当做addApplicationLister方法的参数。

StandardContext.addApplicationLister():

    /**     * Add a new Listener class name to the set of Listeners     * configured for this application.     *     * @param listener Java class name of a listener class     */    public void addApplicationListener(String listener) {        synchronized (applicationListenersLock) {            String results[] =new String[applicationListeners.length + 1];            for (int i = 0; i < applicationListeners.length; i++) {                if (listener.equals(applicationListeners[i])) {                    log.info(sm.getString(                            "standardContext.duplicateListener",listener));                    return;                }                results[i] = applicationListeners[i];            }            results[applicationListeners.length] = listener;            applicationListeners = results;        }        fireContainerEvent("addApplicationListener", listener);        // FIXME - add instance if already started?    }

ContextConfig.fixDocBase():

    protected void fixDocBase()        throws IOException {                Host host = (Host) context.getParent();        String appBase = host.getAppBase();        boolean unpackWARs = true;        if (host instanceof StandardHost) {            unpackWARs = ((StandardHost) host).isUnpackWARs()                 && ((StandardContext) context).getUnpackWAR();        }        File canonicalAppBase = new File(appBase);        if (canonicalAppBase.isAbsolute()) {            canonicalAppBase = canonicalAppBase.getCanonicalFile();        } else {            canonicalAppBase =                 new File(System.getProperty("catalina.base"), appBase)                .getCanonicalFile();        }        String docBase = context.getDocBase();        if (docBase == null) {            // Trying to guess the docBase according to the path            String path = context.getPath();            if (path == null) {                return;            }            if (path.equals("")) {                docBase = "ROOT";            } else {                if (path.startsWith("/")) {                    docBase = path.substring(1).replace('/', '#');                } else {                    docBase = path.replace('/', '#');                }            }        }        File file = new File(docBase);        if (!file.isAbsolute()) {            docBase = (new File(canonicalAppBase, docBase)).getPath();        } else {            docBase = file.getCanonicalPath();        }        file = new File(docBase);        String origDocBase = docBase;                String pathName = context.getPath();        if (pathName.equals("")) {            pathName = "ROOT";        } else {            // Context path must start with '/'            pathName = pathName.substring(1).replace('/', '#');        }        if (docBase.toLowerCase().endsWith(".war") && !file.isDirectory() && unpackWARs) {            URL war = new URL("jar:" + (new File(docBase)).toURI().toURL() + "!/");            docBase = ExpandWar.expand(host, war, pathName);            file = new File(docBase);            docBase = file.getCanonicalPath();            if (context instanceof StandardContext) {                ((StandardContext) context).setOriginalDocBase(origDocBase);            }        } else if (docBase.toLowerCase().endsWith(".war") &&                !file.isDirectory() && !unpackWARs) {            URL war =                new URL("jar:" + (new File (docBase)).toURI().toURL() + "!/");            ExpandWar.validate(host, war, pathName);        } else {            File docDir = new File(docBase);            if (!docDir.exists()) {                File warFile = new File(docBase + ".war");                if (warFile.exists()) {                    URL war =                        new URL("jar:" + warFile.toURI().toURL() + "!/");                    if (unpackWARs) {                        docBase = ExpandWar.expand(host, war, pathName);                        file = new File(docBase);                        docBase = file.getCanonicalPath();                    } else {                        docBase = warFile.getCanonicalPath();                        ExpandWar.validate(host, war, pathName);                    }                }                if (context instanceof StandardContext) {                    ((StandardContext) context).setOriginalDocBase(origDocBase);                }            }        }        if (docBase.startsWith(canonicalAppBase.getPath() + File.separatorChar)) {            docBase = docBase.substring(canonicalAppBase.getPath().length());            docBase = docBase.replace(File.separatorChar, '/');            if (docBase.startsWith("/")) {                docBase = docBase.substring(1);            }        } else {            docBase = docBase.replace(File.separatorChar, '/');        }        context.setDocBase(docBase);    }

解压war包,docBase = ExpandWar.expand(host, war, pathName);

    /**     * Expand the WAR file found at the specified URL into an unpacked     * directory structure, and return the absolute pathname to the expanded     * directory.     *     * @param host Host war is being installed for     * @param war URL of the web application archive to be expanded     *  (must start with "jar:")     * @param pathname Context path name for web application     *     * @exception IllegalArgumentException if this is not a "jar:" URL or if the     *            WAR file is invalid     * @exception IOException if an input/output error was encountered     *  during expansion     */    public static String expand(Host host, URL war, String pathname)        throws IOException {        // Make sure that there is no such directory already existing        File appBase = new File(host.getAppBase());        if (!appBase.isAbsolute()) {            appBase = new File(System.getProperty("catalina.base"),                               host.getAppBase());        }        if (!appBase.exists() || !appBase.isDirectory()) {            throw new IOException                (sm.getString("hostConfig.appBase",                              appBase.getAbsolutePath()));        }                File docBase = new File(appBase, pathname);        if (docBase.exists()) {            // War file is already installed            return (docBase.getAbsolutePath());        }        // Create the new document base directory        docBase.mkdir();        // Expand the WAR into the new document base directory        String canonicalDocBasePrefix = docBase.getCanonicalPath();        if (!canonicalDocBasePrefix.endsWith(File.separator)) {            canonicalDocBasePrefix += File.separator;        }        JarURLConnection juc = (JarURLConnection) war.openConnection();        juc.setUseCaches(false);        JarFile jarFile = null;        InputStream input = null;        boolean success = false;        try {            jarFile = juc.getJarFile();            Enumeration jarEntries = jarFile.entries();            while (jarEntries.hasMoreElements()) {                JarEntry jarEntry = (JarEntry) jarEntries.nextElement();                String name = jarEntry.getName();                File expandedFile = new File(docBase, name);                if (!expandedFile.getCanonicalPath().startsWith(                        canonicalDocBasePrefix)) {                    // Trying to expand outside the docBase                    // Throw an exception to stop the deployment                    throw new IllegalArgumentException(                            sm.getString("expandWar.illegalPath",war, name));                }                int last = name.lastIndexOf('/');                if (last >= 0) {                    File parent = new File(docBase,                                           name.substring(0, last));                    parent.mkdirs();                }                if (name.endsWith("/")) {                    continue;                }                input = jarFile.getInputStream(jarEntry);                // Bugzilla 33636                expand(input, expandedFile);                long lastModified = jarEntry.getTime();                if ((lastModified != -1) && (lastModified != 0)) {                    expandedFile.setLastModified(lastModified);                }                input.close();                input = null;            }            success = true;        } catch (IOException e) {            throw e;        } finally {            if (!success) {                // If something went wrong, delete expanded dir to keep things                 // clean                deleteDir(docBase);            }            if (input != null) {                try {                    input.close();                } catch (Throwable t) {                    ;                }                input = null;            }            if (jarFile != null) {                try {                    jarFile.close();                } catch (Throwable t) {                    ;                }                jarFile = null;            }        }        // Return the absolute path to our new document base directory        return (docBase.getAbsolutePath());    }

初始化,配置都已完成,回到StandardContext.start():

lifecycle.fireLifecycleEvent(START_EVENT, null);

将调用ContextConfig.start():

    protected synchronized void start() {        // Called from StandardContext.start()        if (log.isDebugEnabled())            log.debug(sm.getString("contextConfig.start"));        // Set properties based on DefaultContext        Container container = context.getParent();        if( !context.getOverride() ) {            if( container instanceof Host ) {                // Reset the value only if the attribute wasn't                // set on the context.                xmlValidation = context.getXmlValidation();                if (!xmlValidation) {                    xmlValidation = ((Host)container).getXmlValidation();                }                                xmlNamespaceAware = context.getXmlNamespaceAware();                if (!xmlNamespaceAware){                    xmlNamespaceAware                                 = ((Host)container).getXmlNamespaceAware();                }                container = container.getParent();            }        }        // Process the default and application web.xml files        defaultWebConfig();        applicationWebConfig();        if (!context.getIgnoreAnnotations()) {            applicationAnnotationsConfig();        }        if (ok) {            validateSecurityRoles();        }        // Configure an authenticator if we need one        if (ok)            authenticatorConfig();        // Dump the contents of this pipeline if requested        if ((log.isDebugEnabled()) && (context instanceof ContainerBase)) {            log.debug("Pipeline Configuration:");            Pipeline pipeline = ((ContainerBase) context).getPipeline();            Valve valves[] = null;            if (pipeline != null)                valves = pipeline.getValves();            if (valves != null) {                for (int i = 0; i < valves.length; i++) {                    log.debug("  " + valves[i].getInfo());                }            }            log.debug("======================");        }        // Make our application available if no problems were encountered        if (ok)            context.setConfigured(true);        else {            log.error(sm.getString("contextConfig.unavailable"));            context.setConfigured(false);        }    }

ContextConfig.applicationWebConfig():

    /**     * Process the application configuration file, if it exists.     */    protected void applicationWebConfig() {        String altDDName = null;        // Open the application web.xml file, if it exists        InputStream stream = null;        ServletContext servletContext = context.getServletContext();        if (servletContext != null) {            altDDName = (String)servletContext.getAttribute(                                                        Globals.ALT_DD_ATTR);            if (altDDName != null) {                try {                    stream = new FileInputStream(altDDName);                } catch (FileNotFoundException e) {                    log.error(sm.getString("contextConfig.altDDNotFound",                                           altDDName));                }            }            else {                stream = servletContext.getResourceAsStream                    (Constants.ApplicationWebXml);            }        }        if (stream == null) {            if (log.isDebugEnabled()) {                log.debug(sm.getString("contextConfig.applicationMissing") + " " + context);            }            return;        }                long t1=System.currentTimeMillis();        URL url=null;        // Process the application web.xml file        synchronized (webDigester) {            try {                if (altDDName != null) {                    url = new File(altDDName).toURL();                } else {                    url = servletContext.getResource(                                                Constants.ApplicationWebXml);                }                if( url!=null ) {                    InputSource is = new InputSource(url.toExternalForm());                    is.setByteStream(stream);                    if (context instanceof StandardContext) {                        ((StandardContext) context).setReplaceWelcomeFiles(true);                    }                    webDigester.push(context);                    webDigester.setErrorHandler(new ContextErrorHandler());                    if(log.isDebugEnabled()) {                        log.debug("Parsing application web.xml file at " + url.toExternalForm());                    }                    webDigester.parse(is);                    if (parseException != null) {                        ok = false;                    }                } else {                    log.info("No web.xml, using defaults " + context );                }            } catch (SAXParseException e) {                log.error(sm.getString("contextConfig.applicationParse", url.toExternalForm()), e);                log.error(sm.getString("contextConfig.applicationPosition",                                 "" + e.getLineNumber(),                                 "" + e.getColumnNumber()));                ok = false;            } catch (Exception e) {                log.error(sm.getString("contextConfig.applicationParse", url.toExternalForm()), e);                ok = false;            } finally {                webDigester.reset();                parseException = null;                try {                    if (stream != null) {                        stream.close();                    }                } catch (IOException e) {                    log.error(sm.getString("contextConfig.applicationClose"), e);                }            }        }        webRuleSet.recycle();        long t2=System.currentTimeMillis();        if (context instanceof StandardContext) {            ((StandardContext) context).setStartupTime(t2-t1);        }    }

解析规则的栈底将是StandardContext对象,解析web.xml
webDigester.push(context);
webDigester.parse(is);
启动web.xml配置文件中的listener:

            // Configure and call application event listeners            if (ok) {                if (!listenerStart()) {                    log.error( "Error listenerStart");                    ok = false;                }            }

StandardContext.listenerStart():

    /**     * Configure the set of instantiated application event listeners     * for this Context.  Return <code>true</code> if all listeners wre     * initialized successfully, or <code>false</code> otherwise.     */    public boolean listenerStart() {        if (log.isDebugEnabled())            log.debug("Configuring application event listeners");        // Instantiate the required listeners        ClassLoader loader = getLoader().getClassLoader();        String listeners[] = findApplicationListeners();        Object results[] = new Object[listeners.length];        boolean ok = true;        for (int i = 0; i < results.length; i++) {            if (getLogger().isDebugEnabled())                getLogger().debug(" Configuring event listener class '" +                    listeners[i] + "'");            try {                Class clazz = loader.loadClass(listeners[i]);                results[i] = clazz.newInstance();                // Annotation processing                if (!getIgnoreAnnotations()) {                    getAnnotationProcessor().processAnnotations(results[i]);                    getAnnotationProcessor().postConstruct(results[i]);                }            } catch (Throwable t) {                getLogger().error                    (sm.getString("standardContext.applicationListener",                                  listeners[i]), t);                ok = false;            }        }        if (!ok) {            getLogger().error(sm.getString("standardContext.applicationSkipped"));            return (false);        }        // Sort listeners in two arrays        ArrayList eventListeners = new ArrayList();        ArrayList lifecycleListeners = new ArrayList();        for (int i = 0; i < results.length; i++) {            if ((results[i] instanceof ServletContextAttributeListener)                || (results[i] instanceof ServletRequestAttributeListener)                || (results[i] instanceof ServletRequestListener)                || (results[i] instanceof HttpSessionAttributeListener)) {                eventListeners.add(results[i]);            }            if ((results[i] instanceof ServletContextListener)                || (results[i] instanceof HttpSessionListener)) {                lifecycleListeners.add(results[i]);            }        }        setApplicationEventListeners(eventListeners.toArray());        setApplicationLifecycleListeners(lifecycleListeners.toArray());        // Send application start events        if (getLogger().isDebugEnabled())            getLogger().debug("Sending application start events");        Object instances[] = getApplicationLifecycleListeners();        if (instances == null)            return (ok);        ServletContextEvent event =          new ServletContextEvent(getServletContext());        for (int i = 0; i < instances.length; i++) {            if (instances[i] == null)                continue;            if (!(instances[i] instanceof ServletContextListener))                continue;            ServletContextListener listener =                (ServletContextListener) instances[i];            try {                fireContainerEvent("beforeContextInitialized", listener);                listener.contextInitialized(event);                fireContainerEvent("afterContextInitialized", listener);            } catch (Throwable t) {                fireContainerEvent("afterContextInitialized", listener);                getLogger().error                    (sm.getString("standardContext.listenerStart",                                  instances[i].getClass().getName()), t);                ok = false;            }        }        return (ok);    }

启动web.xml配置文件中的filter:

            // Configure and call application filters            if (ok) {                if (!filterStart()) {                    log.error( "Error filterStart");                    ok = false;                }            }

StandardContext.filterStart():

    /**     * Configure and initialize the set of filters for this Context.     * Return <code>true</code> if all filter initialization completed     * successfully, or <code>false</code> otherwise.     */    public boolean filterStart() {        if (getLogger().isDebugEnabled())            getLogger().debug("Starting filters");        // Instantiate and record a FilterConfig for each defined filter        boolean ok = true;        synchronized (filterConfigs) {            filterConfigs.clear();            Iterator names = filterDefs.keySet().iterator();            while (names.hasNext()) {                String name = (String) names.next();                if (getLogger().isDebugEnabled())                    getLogger().debug(" Starting filter '" + name + "'");                ApplicationFilterConfig filterConfig = null;                try {                    filterConfig = new ApplicationFilterConfig                      (this, (FilterDef) filterDefs.get(name));                    filterConfigs.put(name, filterConfig);                } catch (Throwable t) {                    getLogger().error                        (sm.getString("standardContext.filterStart", name), t);                    ok = false;                }            }        }        return (ok);    }

其实就是创建Filter配置信息的对象,并未创建Filter实例。而至于要start多少监听器,那就得看项目的web.xml了。

 

原创粉丝点击