All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.catalina.startup.HostConfig Maven / Gradle / Ivy

There is a newer version: 4.1.2.181
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 * Copyright 2004 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.catalina.startup;


import org.apache.catalina.*;
import org.apache.catalina.core.StandardHost;
import org.apache.naming.resources.ResourceAttributes;

import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import java.io.*;
import java.net.URL;
import java.text.MessageFormat;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Startup event listener for a Host that configures the properties
 * of that Host, and the associated defined contexts.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 * @version $Revision: 1.4 $ $Date: 2006/10/03 20:19:13 $
 */

public class HostConfig
    implements LifecycleListener {
    
    private static final Logger log = LogFacade.getLogger();
    private static final ResourceBundle rb = log.getResourceBundle();

    // ----------------------------------------------------- Instance Variables


    /**
     * App base.
     */
    private File appBase = null;


    /**
     * Config base.
     */
    private File configBase = null;


    /**
     * The Java class name of the Context configuration class we should use.
     */
    protected String configClass = "org.apache.catalina.startup.ContextConfig";


    /**
     * The Java class name of the Context implementation we should use.
     */
    protected String contextClass = "org.apache.catalina.core.StandardContext";


    /**
     * The debugging detail level for this component.
     */
    protected int debug = 0;


    /**
     * The names of applications that we have auto-deployed (to avoid
     * double deployment attempts).
     */
    protected List deployed = new ArrayList();


    /**
     * The Host we are associated with.
     */
    protected Host host = null;

    /**
     * Should we deploy XML Context config files?
     */
    private boolean deployXML = false;


    /**
     * Should we unpack WAR files when auto-deploying applications in the
     * appBase directory?
     */
    private boolean unpackWARs = false;


    /**
     * Last modified dates of the web.xml files of the contexts, keyed by
     * context name.
     */
    private Map webXmlLastModified = new HashMap();


    /**
     * Last modified dates of the Context xml files of the contexts, keyed by
     * context name.
     */
    private Map contextXmlLastModified = new HashMap();


    /**
     * Last modified dates of the source WAR files, keyed by WAR name.
     */
    private HashMap warLastModified = new HashMap();


    /**
     * Attribute value used to turn on/off XML validation
     */
    private boolean xmlValidation = false;


    /**
     * Attribute value used to turn on/off XML namespace awarenes.
     */
    private boolean xmlNamespaceAware = false;


    /**
     * The list of Wars in the appBase to be ignored because they are invalid
     * (e.g. contain /../ sequences).
     */
    protected Set invalidWars = new HashSet();


    // ------------------------------------------------------------- Properties


    /**
     * Return the Context configuration class name.
     */
    public String getConfigClass() {

        return (this.configClass);

    }


    /**
     * Set the Context configuration class name.
     *
     * @param configClass The new Context configuration class name.
     */
    public void setConfigClass(String configClass) {

        this.configClass = configClass;

    }


    /**
     * Return the Context implementation class name.
     */
    public String getContextClass() {

        return (this.contextClass);

    }


    /**
     * Set the Context implementation class name.
     *
     * @param contextClass The new Context implementation class name.
     */
    public void setContextClass(String contextClass) {

        this.contextClass = contextClass;

    }


    /**
     * Return the debugging detail level for this component.
     */
    public int getDebug() {

        return (this.debug);

    }


    /**
     * Set the debugging detail level for this component.
     *
     * @param debug The new debugging detail level
     */
    public void setDebug(int debug) {

        this.debug = debug;

    }


    /**
     * Return the deploy XML config file flag for this component.
     */
    public boolean isDeployXML() {

        return (this.deployXML);

    }


    /**
     * Set the deploy XML config file flag for this component.
     *
     * @param deployXML The new deploy XML flag
     */
    public void setDeployXML(boolean deployXML) {

        this.deployXML= deployXML;

    }


    /**
     * Return the unpack WARs flag.
     */
    public boolean isUnpackWARs() {

        return (this.unpackWARs);

    }


    /**
     * Set the unpack WARs flag.
     *
     * @param unpackWARs The new unpack WARs flag
     */
    public void setUnpackWARs(boolean unpackWARs) {

        this.unpackWARs = unpackWARs;

    }
    
    
     /**
     * Set the validation feature of the XML parser used when
     * parsing xml instances.
     * @param xmlValidation true to enable xml instance validation
     */
    public void setXmlValidation(boolean xmlValidation){
        this.xmlValidation = xmlValidation;
    }

    /**
     * Get the server.xml  attribute's xmlValidation.
     * @return true if validation is enabled.
     *
     */
    public boolean getXmlValidation(){
        return xmlValidation;
    }

    /**
     * Get the server.xml  attribute's xmlNamespaceAware.
     * @return true if namespace awarenes is enabled.
     *
     */
    public boolean getXmlNamespaceAware(){
        return xmlNamespaceAware;
    }


    /**
     * Set the namespace aware feature of the XML parser used when
     * parsing xml instances.
     * @param xmlNamespaceAware true to enable namespace awareness
     */
    public void setXmlNamespaceAware(boolean xmlNamespaceAware){
        this.xmlNamespaceAware=xmlNamespaceAware;
    }    


    // --------------------------------------------------------- Public Methods


    /**
     * Process the START event for an associated Host.
     *
     * @param event The lifecycle event that has occurred
     */
    public void lifecycleEvent(LifecycleEvent event) {

        if (event.getType().equals("check"))
            check();

        // Identify the host we are associated with
        try {
            host = (Host) event.getLifecycle();
            if (host instanceof StandardHost) {
                int hostDebug = ((StandardHost) host).getDebug();
                if (hostDebug > this.debug) {
                    this.debug = hostDebug;
                }
                setDeployXML(((StandardHost) host).isDeployXML());
                setUnpackWARs(((StandardHost) host).isUnpackWARs());
                setXmlNamespaceAware(((StandardHost) host).getXmlNamespaceAware());
                setXmlValidation(((StandardHost) host).getXmlValidation());
            }
        } catch (ClassCastException e) {
            String msg = MessageFormat.format(rb.getString(LogFacade.LIFECYCLE_OBJECT_NOT_HOST_EXCEPTION),
                                              event.getLifecycle());
            log.log(Level.SEVERE, msg, e);
            return;
        }

        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.START_EVENT))
            start();
        else if (event.getType().equals(Lifecycle.STOP_EVENT))
            stop();

    }


    // ------------------------------------------------------ Protected Methods


    /**
     * Return a File object representing the "application root" directory
     * for our associated Host.
     */
    protected File appBase() {

        if (appBase != null) {
            return appBase;
        }

        File file = new File(host.getAppBase());
        if (!file.isAbsolute())
            file = new File(System.getProperty("catalina.base"),
                            host.getAppBase());
        try {
            appBase = file.getCanonicalFile();
        } catch (IOException e) {
            appBase = file;
        }
        return (appBase);

    }


    /**
     * Return a File object representing the "configuration root" directory
     * for our associated Host.
     */
    protected File configBase() {

        if (configBase != null) {
            return configBase;
        }

        File file = new File(System.getProperty("catalina.base"), "conf");
        Container parent = host.getParent();
        if ((parent != null) && (parent instanceof Engine)) {
            file = new File(file, parent.getName());
        }
        file = new File(file, host.getName());
        try {
            configBase = file.getCanonicalFile();
        } catch (IOException e) {
            configBase = file;
        }
        return (configBase);

    }


    /**
     * Deploy applications for any directories or WAR files that are found
     * in our "application root" directory.
     */
    protected void deployApps() {

        if (!(host instanceof Deployer))
            return;

        File appBase = appBase();
        if (!appBase.exists() || !appBase.isDirectory())
            return;
        File configBase = configBase();
        if (configBase.exists() && configBase.isDirectory()) {
            String configFiles[] = configBase.list();
            deployDescriptors(configBase, configFiles);
        }

        String files[] = appBase.list();
        deployWARs(appBase, files);
        deployDirectories(appBase, files);

    }


    /**
     * Deploy XML context descriptors.
     */
    protected void deployDescriptors(File configBase, String[] files) {

        if (!deployXML)
           return;

        for (int i = 0; i < files.length; i++) {

            if (files[i].equalsIgnoreCase("META-INF"))
                continue;
            if (files[i].equalsIgnoreCase("WEB-INF"))
                continue;
            if (deployed.contains(files[i]))
                continue;
            File dir = new File(configBase, files[i]);
            if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".xml")) {

                deployed.add(files[i]);

                // Calculate the context path and make sure it is unique
                String file = files[i].substring(0, files[i].length() - 4);
                String contextPath = "/" + file.replace('_', '/');
                if (file.equals("ROOT")) {
                    contextPath = "";
                }

                // Assume this is a configuration descriptor and deploy it
                if (log.isLoggable(Level.FINE)) {
                    log.log(Level.FINE, LogFacade.DEPLOYING_CONFIG_DESCRIPTOR, files[i]);
                }
                try {
                    if (host.findChild(contextPath) != null) {
                        if ((deployed.contains(file))
                            || (deployed.contains(file + ".war"))) {
                            // If this is a newly added context file and 
                            // it overrides a context with a simple path, 
                            // that was previously deployed by the auto
                            // deployer, undeploy the context
                            ((Deployer) host).remove(contextPath);
                        } else {
                            continue;
                        }
                    }
                    URL config =
                        new URL("file", null, dir.getCanonicalPath());
                    ((Deployer) host).install(config, null);
                } catch (Throwable t) {
                    String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_DEPLOYING_CONFIG_DESCRIPTOR_EXCEPTION),
                                                      files[i]);
                    log.log(Level.SEVERE, msg, t);
                }
            }
        }
    }


    /**
     * Deploy WAR files.
     */
    protected void deployWARs(File appBase, String[] files) {

        for (int i = 0; i < files.length; i++) {

            if (files[i].equalsIgnoreCase("META-INF"))
                continue;
            if (files[i].equalsIgnoreCase("WEB-INF"))
                continue;
            if (deployed.contains(files[i]))
                continue;
            File dir = new File(appBase, files[i]);
            if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".war") && dir.isFile()
                    && !invalidWars.contains(files[i])) {

                deployed.add(files[i]);

                // Calculate the context path and make sure it is unique
                String contextPath = "/" + files[i];
                int period = contextPath.lastIndexOf(".");
                if (period >= 0)
                    contextPath = contextPath.substring(0, period);

                // Check for WARs with /../ /./ or similar sequences in the name
                if (!validateContextPath(appBase, contextPath)) {
                    log.log(Level.SEVERE, LogFacade.INVALID_WAR_NAME_EXCEPTION, files[i]);
                    invalidWars.add(files[i]);
                    continue;
                }

                if (contextPath.equals("/ROOT"))
                    contextPath = "";
                if (host.findChild(contextPath) != null)
                    continue;

                // 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, files[i].substring
                     (0, files[i].lastIndexOf(".")) + ".xml");
                if (!xml.exists()) {
                    try {
                        jar = new JarFile(dir);
                        entry = jar.getJarEntry("META-INF/context.xml");
                        if (entry != null) {
                            istream = jar.getInputStream(entry);
                            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;
                            deployDescriptors(configBase(), configBase.list());
                            return;
                        }
                    } catch (IOException e) {
                        // Ignore and continue
                    } finally {
                        if (ostream != null) {
                            try {
                                ostream.close();
                            } catch (Throwable t) {
                                ;
                            }
                            ostream = null;
                        }
                        if (istream != null) {
                            try {
                                istream.close();
                            } catch (Throwable t) {
                                ;
                            }
                            istream = null;
                        }
                        entry = null;
                        if (jar != null) {
                            try {
                                jar.close();
                            } catch (Throwable t) {
                                ;
                            }
                            jar = null;
                        }
                    }
                }

                if (isUnpackWARs()) {

                    // Expand and deploy this application as a directory
                    if (log.isLoggable(Level.FINE)) {
                        log.log(Level.FINE, LogFacade.EXPANDING_WEB_APP, files[i]);
                    }
                    URL url = null;
                    String path = null;
                    try {
                        url = new URL("jar:file:" +
                                      dir.getCanonicalPath() + "!/");
                        path = ExpandWar.expand(host, url);
                    } catch (IOException e) {
                        // JAR decompression failure
                        log.log(Level.WARNING, LogFacade.EXPANDING_WEB_APP_EXCEPTION, files[i]);
                        continue;
                    } catch (Throwable t) {
                        String msg = MessageFormat.format(rb.getString(LogFacade.EXPANDING_WEB_APP_ARCHIVE_EXCEPTION),
                                                          files[i]);
                        log.log(Level.SEVERE, msg, t);
                        continue;
                    }
                    try {
                        if (path != null) {
                            url = new URL("file:" + path);
                            ((Deployer) host).install(contextPath, url);
                        }
                    } catch (Throwable t) {
                        String msg = MessageFormat.format(rb.getString(LogFacade.EXPANDING_WEB_APP_ARCHIVE_EXCEPTION),
                                                          files[i]);
                        log.log(Level.SEVERE, msg, t);
                    }

                } else {

                    // Deploy the application in this WAR file
                    if (log.isLoggable(Level.INFO)) {
                        log.log(Level.INFO, LogFacade.DEPLOYING_WEB_APP_ARCHIVE, files[i]);
                    }
                    try {
                        URL url = new URL("file", null,
                                          dir.getCanonicalPath());
                        url = new URL("jar:" + url.toString() + "!/");
                        ((Deployer) host).install(contextPath, url);
                    } catch (Throwable t) {
                        String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_DEPLOYING_WEB_APP_ARCHIVE_EXCEPTION),
                                                          files[i]);
                        log.log(Level.SEVERE, msg, t);
                    }
                }
            }
        }
    }


    /**
     * Deploy directories.
     */
    protected void deployDirectories(File appBase, String[] files) {

        for (int i = 0; i < files.length; i++) {

            if (files[i].equalsIgnoreCase("META-INF"))
                continue;
            if (files[i].equalsIgnoreCase("WEB-INF"))
                continue;
            if (deployed.contains(files[i]))
                continue;
            File dir = new File(appBase, files[i]);
            if (dir.isDirectory()) {

                deployed.add(files[i]);

                // Make sure there is an application configuration directory
                // This is needed if the Context appBase is the same as the
                // web server document root to make sure only web applications
                // are deployed and not directories for web space.
                File webInf = new File(dir, "/WEB-INF");
                if (!webInf.exists() || !webInf.isDirectory() ||
                    !webInf.canRead())
                    continue;

                // Calculate the context path and make sure it is unique
                String contextPath = "/" + files[i];
                if (files[i].equals("ROOT"))
                    contextPath = "";
                if (host.findChild(contextPath) != null)
                    continue;

                // Deploy the application in this directory
                if (log.isLoggable(Level.FINE)) {
                    log.log(Level.FINE, LogFacade.DEPLOYING_WEB_APP_DIR, files[i]);
                }
                long t1=System.currentTimeMillis();
                try {
                    URL url = new URL("file", null, dir.getCanonicalPath());
                    ((Deployer) host).install(contextPath, url);
                } catch (Throwable t) {
                    String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_DEPLOYING_WEB_APP_DIR),
                                                      files[i]);
                    log.log(Level.SEVERE, msg, t);
                }
                long t2=System.currentTimeMillis();
                if( (t2-t1) > 200 && log.isLoggable(Level.FINE) )
                    log.log(Level.FINE, "Deployed " + files[i] + " " + (t2-t1));
            }

        }

    }


    private boolean validateContextPath(File appBase, String contextPath) {
        // More complicated than the ideal as the canonical path may or may
        // not end with File.separator for a directory
        
        StringBuilder docBase;
        String canonicalDocBase = null;
        
        try {
            String canonicalAppBase = appBase.getCanonicalPath();
            docBase = new StringBuilder(canonicalAppBase);
            if (canonicalAppBase.endsWith(File.separator)) {
                docBase.append(contextPath.substring(1).replace(
                        '/', File.separatorChar));
            } else {
                docBase.append(contextPath.replace('/', File.separatorChar));
            }
            // At this point docBase should be canonical but will not end
            // with File.separator
            
            canonicalDocBase =
                (new File(docBase.toString())).getCanonicalPath();
    
            // If the canonicalDocBase ends with File.separator, add one to
            // docBase before they are compared
            if (canonicalDocBase.endsWith(File.separator)) {
                docBase.append(File.separator);
            }
        } catch (IOException ioe) {
            return false;
        }
        
        // Compare the two. If they are not the same, the contextPath must
        // have /../ like sequences in it 
        return canonicalDocBase.equals(docBase.toString());
    }


    /**
     * Check deployment descriptors last modified date.
     */
    protected void checkContextLastModified() {

        if (!(host instanceof Deployer))
            return;

        Deployer deployer = (Deployer) host;

        String[] contextNames = deployer.findDeployedApps();

        for (int i = 0; i < contextNames.length; i++) {

            String contextName = contextNames[i];
            Context context = deployer.findDeployedApp(contextName);

            if (!(context instanceof Lifecycle))
                continue;

            try {
                DirContext resources = context.getResources();
                if (resources == null) {
                    // This can happen if there was an error initializing
                    // the context
                    continue;
                }
                ResourceAttributes webXmlAttributes = 
                    (ResourceAttributes) 
                    resources.getAttributes("/WEB-INF/web.xml");
                ResourceAttributes webInfAttributes = 
                    (ResourceAttributes) 
                    resources.getAttributes("/WEB-INF");
                long newLastModified = webXmlAttributes.getLastModified();
                long webInfLastModified = webInfAttributes.getLastModified();
                Long lastModified = webXmlLastModified.get(contextName);
                if (lastModified == null) {
                    webXmlLastModified.put
                        (contextName, Long.valueOf(newLastModified));
                } else {
                    if (lastModified.longValue() != newLastModified) {
                        if (newLastModified > (webInfLastModified + 5000)) {
                            webXmlLastModified.remove(contextName);
                            restartContext(context);
                        } else {
                            webXmlLastModified.put
                                (contextName, Long.valueOf(newLastModified));
                        }
                    }
                }
            } catch (NamingException e) {
                ; // Ignore
            }

            Long lastModified = contextXmlLastModified.get(contextName);
            String configBase = configBase().getPath();
            String configFileName = context.getConfigFile();
            if (configFileName != null) {
                File configFile = new File(configFileName);
                if (!configFile.isAbsolute()) {
                    configFile = new File(System.getProperty("catalina.base"),
                                          configFile.getPath());
                }
                long newLastModified = configFile.lastModified();
                if (lastModified == null) {
                    contextXmlLastModified.put
                        (contextName, Long.valueOf(newLastModified));
                } else {
                    if (lastModified.longValue() != newLastModified) {
                        contextXmlLastModified.remove(contextName);
                        String fileName = configFileName;
                        if (fileName.startsWith(configBase)) {
                            fileName = 
                                fileName.substring(configBase.length() + 1);
                            try {
                                deployed.remove(fileName);
                                if (host.findChild(contextName) != null) {
                                    ((Deployer) host).remove(contextName);
                                }
                            } catch (Throwable t) {
                                String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_UNDEPLOYING_JAR_FILE_EXCEPTION),
                                                                  fileName);
                                log.log(Level.SEVERE, msg, t);
                            }
                            deployApps();
                        }
                    }
                }
            }

        }

        // Check for WAR modification
        if (isUnpackWARs()) {
            File appBase = appBase();
            if (!appBase.exists() || !appBase.isDirectory())
                return;
            String files[] = appBase.list();

            for (int i = 0; i < files.length; i++) {
                if (files[i].endsWith(".war")) {
                    File dir = new File(appBase, files[i]);
                    Long lastModified = warLastModified.get(files[i]);
                    long dirLastModified = dir.lastModified();
                    if (lastModified == null) {
                        warLastModified.put
                            (files[i], Long.valueOf(dir.lastModified()));
                    } else if (dirLastModified > lastModified.longValue()) {
                        // The WAR has been modified: redeploy
                        String expandedDir = files[i];
                        int period = expandedDir.lastIndexOf(".");
                        if (period >= 0)
                            expandedDir = expandedDir.substring(0, period);
                        File expanded = new File(appBase, expandedDir);
                        String contextPath = "/" + expandedDir;
                        if (contextPath.equals("/ROOT"))
                            contextPath = "";
                        if (dirLastModified > expanded.lastModified()) {
                            try {
                                // Undeploy current application
                                deployed.remove(files[i]);
                                deployed.remove(expandedDir + ".xml");
                                if (host.findChild(contextPath) != null) {
                                    ((Deployer) host).remove(contextPath, 
                                                             false);
                                    ExpandWar.deleteDir(expanded);
                                }
                            } catch (Throwable t) {
                                String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_UNDEPLOYING_JAR_FILE_EXCEPTION),
                                                                  files[i]);
                                log.log(Level.SEVERE, msg, t);
                            }
                            deployApps();
                        }
                        // If deployment was successful, reset 
                        // the last modified values
                        if (host.findChild(contextPath) != null) {
                            webXmlLastModified.remove(contextPath);
                            warLastModified.put
                                (files[i], Long.valueOf(dir.lastModified()));
                        }
                    }
                }
            }
        }

    }


    protected boolean restartContext(Context context) {
        boolean result = true;
        if (log.isLoggable(Level.INFO)) {
            log.log(Level.INFO, LogFacade.RESTART_CONTEXT_INFO, context.getName());
        }

        /*
        try {
            StandardContext sctx=(StandardContext)context;
            sctx.reload();
        } catch( Exception ex ) {
            log.warn("Erorr stopping context " + context.getName()  +  " " +
                    ex.toString());
        }
        */
        try {
            ((Lifecycle) context).stop();
        } catch( Exception ex ) {
            String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_DURING_CONTEXT_STOP_EXCEPTION),
                                              context.getName());
            log.log(Level.WARNING, msg, ex);
        }
        // if the context was not started ( for example an error in web.xml)
        // we'll still get to try to start
        try {
            ((Lifecycle) context).start();
        } catch (Exception e) {
            String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_DURING_CONTEXT_RESTART_EXCEPTION),
                                              context.getName());
            log.log(Level.WARNING, msg, e);
            result = false;
        }
        
        return result;
    }


    /**
     * Expand the WAR file found at the specified URL into an unpacked
     * directory structure, and return the absolute pathname to the expanded
     * directory.
     *
     * @param war URL of the web application archive to be expanded
     *  (must start with "jar:")
     *
     * @exception IllegalArgumentException if this is not a "jar:" URL
     * @exception IOException if an input/output error was encountered
     *  during expansion
     */
    protected String expand(URL war) throws IOException {

        return ExpandWar.expand(host,war);
    }


    /**
     * Expand the specified input stream into the specified directory, creating
     * a file named from the specified relative path.
     *
     * @param input InputStream to be copied
     * @param docBase Document base directory into which we are expanding
     * @param name Relative pathname of the file to be created
     *
     * @exception IOException if an input/output error occurs
     */
    protected void expand(InputStream input, File docBase, String name)
        throws IOException {

        ExpandWar.expand(input,docBase,name);
    }


    /**
     * Log a message on the Logger associated with our Host (if any)
     *
     * @param message Message to be logged
     */
    protected void log(String message) {

        org.apache.catalina.Logger logger = null;
        if (host != null)
            logger = host.getLogger();
        if (logger != null)
            logger.log("HostConfig[" + host.getName() + "]: " + message);
        else
            log.info(message);
    }


    /**
     * Log a message on the Logger associated with our Host (if any)
     *
     * @param message Message to be logged
     * @param throwable Associated exception
     */
    protected void log(String message, Throwable throwable) {

        org.apache.catalina.Logger logger = null;
        if (host != null)
            logger = host.getLogger();
        if (logger != null)
            logger.log("HostConfig[" + host.getName() + "] "
                       + message, throwable);
        else {
            log.log(Level.SEVERE, message, throwable);
        }

    }


    /**
     * Process a "start" event for this Host.
     */
    public void start() {

        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, LogFacade.PROCESSING_START);
        if (host.getDeployOnStartup()) {
            deployApps();
        } else {
            // Deploy descriptors anyway (it should be equivalent to being
            // part of server.xml)
            File configBase = configBase();
            if (configBase.exists() && configBase.isDirectory()) {
                String configFiles[] = configBase.list();
                deployDescriptors(configBase, configFiles);
            }
        } 

    }


    /**
     * Process a "stop" event for this Host.
     */
    public void stop() {

        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, LogFacade.PROCESSING_STOP);
        undeployApps();

        appBase = null;
        configBase = null;

    }


    /**
     * Undeploy all deployed applications.
     */
    protected void undeployApps() {

        if (!(host instanceof Deployer))
            return;
        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, LogFacade.UNDEPLOYING_WEB_APP);

        String contextPaths[] = ((Deployer) host).findDeployedApps();
        for (int i = 0; i < contextPaths.length; i++) {
            if (log.isLoggable(Level.FINE)) {
                log.log(Level.FINE, LogFacade.UNDEPLOYING_CONTEXT, contextPaths[i]);
            }
            try {
                ((Deployer) host).remove(contextPaths[i]);
            } catch (Throwable t) {
                String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_UNDEPLOYING_WEB_APP_EXCEPTION),
                                                  contextPaths[i]);
                log.log(Level.SEVERE, msg, t);
            }
        }

        webXmlLastModified.clear();
        deployed.clear();

    }


    /**
     * Deploy webapps.
     */
    protected void check() {

        if (host.getAutoDeploy()) {
            // Deploy apps if the Host allows auto deploying
            deployApps();
            // Check for web.xml modification
            checkContextLastModified();
        }

    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy