tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From craig...@locus.apache.org
Subject cvs commit: jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup HostConfig.java LocalStrings.properties
Date Wed, 04 Oct 2000 23:03:08 GMT
craigmcc    00/10/04 16:03:06

  Modified:    catalina/src/share/org/apache/catalina/core
                        LocalStrings.properties StandardHost.java
               catalina/src/share/org/apache/catalina/startup
                        HostConfig.java LocalStrings.properties
  Added:       catalina/src/share/org/apache/catalina Deployer.java
  Log:
  Add a new extension of Container called Deployer, which represents a
  Container into which web applications can be deployed and undeployed.  In
  the current environment, StandardHost is the only container implementation
  that is also a deployer -- but additional such containers can be created
  (such as the forthcoming specialized container for the Apache connector).
  
  Implemented the deploy() and undeploy() functionality in StandardHost.
  Now, Tomcat 4.0 is capable of "hot" application loading and unloading,
  given just a context path and the URL of a WAR file.  This will be of
  tremendous use in administrative and management applications.
  
  As before, application deployment from a WAR file in the application base
  directory ($CATALINA_HOME/webapps for the default configuration) will
  cause the WAR to be automatically expanded.  However, the new undeploy
  functionality also deletes the directory when the application is
  undeployed -- the theory is that the developer will be replacing the WAR
  anyway in this scenario, and this is a common complaint about the way that
  Tomcat 3.x works (once the directory is expanded the user has to remember
  to delete it).
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Deployer.java
  
  Index: Deployer.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Deployer.java,v
1.1 2000/10/04 23:03:03 craigmcc Exp $
   * $Revision: 1.1 $
   * $Date: 2000/10/04 23:03:03 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  
  package org.apache.catalina;
  
  
  import java.io.IOException;
  import java.net.URL;
  
  
  /**
   * A <b>Deployer</b> is a specialized Container into which web applications
   * can be deployed and undeployed.  Such a Container will create and install
   * child Context instances for each deployed application.  The unique key
   * for each web application will be the context path to which it is attached.
   *
   * @author Craig R. McClanahan
   * @version $Revision: 1.1 $ $Date: 2000/10/04 23:03:03 $
   */
  
  public interface Deployer extends Container {
  
  
      // ----------------------------------------------------- Manifest Constants
  
  
      /**
       * The ContainerEvent event type sent when a new application is
       * deployed by <code>deploy()</code>.
       */
      public static final String DEPLOY_EVENT = "deploy";
  
  
      /**
       * The ContainerEvent event type sent when an existing application is
       * undeployed by <code>undeploy()</code>.
       */
      public static final String UNDEPLOY_EVENT = "undeploy";
  
  
      // --------------------------------------------------------- Public Methods
  
  
      /**
       * Deploy a new web application, whose web application archive is at the
       * specified URL, into this container with the specified context path.
       * A context path of "" (the empty string) should be used for the root
       * application for this container.  Otherwise, the context path must
       * start with a slash.
       * <p>
       * If this application is successfully deployed, a ContainerEvent of type
       * <code>DEPLOY_EVENT</code> will be sent to all registered listeners,
       * with the newly created <code>Context</code> as an argument.
       *
       * @param contextPath The context path to which this application should
       *  be deployed (must be unique)
       * @param war A URL of type "jar:" that points to a WAR file, or type
       *  "file:" that points to an unpacked directory structure containing
       *  the web application to be deployed
       *
       * @exception IllegalArgumentException if the specified context path
       *  is malformed (it must be "" or start with a slash)
       * @exception IllegalArgumentException if the specified context path
       *  is already attached to an existing web application
       * @exception IOException if an input/output error was encountered
       *  during deployment
       */
      public void deploy(String contextPath, URL war) throws IOException;
  
  
      /**
       * Return the Context for the deployed application that is associated
       * with the specified context path (if any); otherwise return
       * <code>null</code>.
       *
       * @param contextPath The context path of the requested web application
       */
      public Context findDeployedApp(String contextPath);
  
  
      /**
       * Return the context paths of all deployed web applications in this
       * Container.  If there are no deployed applications, a zero-length
       * array is returned.
       */
      public String[] findDeployedApps();
  
  
      /**
       * Undeploy an existing web application, attached to the specified context
       * path.  If this application is successfully undeployed, a
       * ContainerEvent of type <code>UNDEPLOY_EVENT</code> will be sent to all
       * registered listeners, with the undeployed <code>Context</code> as
       * an argument.
       *
       * @param contextPath The context path of the application to be undeployed
       *
       * @exception IllegalArgumentException if the specified context path
       *  is malformed (it must be "" or start with a slash)
       * @exception IllegalArgumentException if the specified context path does
       *  not identify a currently deployed web application
       * @exception IOException if an input/output error occurs during
       *  undeployment
       */
      public void undeploy(String contextPath) throws IOException;
  
  
  }
  
  
  
  1.11      +14 -1     jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/LocalStrings.properties,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- LocalStrings.properties	2000/10/03 21:30:34	1.10
  +++ LocalStrings.properties	2000/10/04 23:03:03	1.11
  @@ -49,14 +49,27 @@
   standardEngine.notStarted=Engine has not yet been started
   standardEngine.unfoundHost=Virtual host {0} not found
   standardEngine.unknownHost=No server host specified in this request
  +standardHost.accessBase=Cannot access document base directory {0}
   standardHost.alreadyStarted=Host has already been started
  -standardHost.mappingError=MAPPING configuration error for requset URI {0}
  +standardHost.appBase=Application base directory {0} does not exist
  +standardHost.deploying=Deploying web application at context path {0} from URL {1}
  +standardHost.deployError=Error deploying application at context path {0}
  +standardHost.docBase=Document base directory {0} already exists
  +standardHost.mappingError=MAPPING configuration error for request URI {0}
   standardHost.noContext=No Context configured to process this request
   standardHost.noHost=No Host configured to process this request
   standardHost.notContext=Child of a Host must be a Context
   standardHost.notStarted=Host has not yet been started
   standardHost.nullName=Host name is required
  +standardHost.pathFormat=Invalid context path: {0}
  +standardHost.pathMissing=Context path {0} is not currently in use
  +standardHost.pathRequired=Context path is required
  +standardHost.pathUsed=Context path {0} is already in use
  +standardHost.undeploying=Undeploying web application at context path {0}
  +standardHost.undeployError=Error undeploying application at context path {0}
   standardHost.unfoundContext=Cannot find context for request URI {0}
  +standardHost.warRequired=URL to web application archive is required
  +standardHost.warURL=Invalid URL for web application archive: {0}
   standardServer.addContainer.ise=No connectors available to associate this container with
   standardServer.start.connectors=At least one connector is not associated with any container
   standardServer.start.started=This server has already been started
  
  
  
  1.3       +410 -5    jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardHost.java
  
  Index: StandardHost.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardHost.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- StandardHost.java	2000/08/12 18:57:29	1.2
  +++ StandardHost.java	2000/10/04 23:03:04	1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardHost.java,v
1.2 2000/08/12 18:57:29 craigmcc Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/08/12 18:57:29 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardHost.java,v
1.3 2000/10/04 23:03:04 craigmcc Exp $
  + * $Revision: 1.3 $
  + * $Date: 2000/10/04 23:03:04 $
    *
    * ====================================================================
    *
  @@ -65,15 +65,28 @@
   package org.apache.catalina.core;
   
   
  +import java.io.BufferedOutputStream;
  +import java.io.File;
  +import java.io.FileOutputStream;
  +import java.io.InputStream;
   import java.io.IOException;
  +import java.net.JarURLConnection;
  +import java.net.URL;
  +import java.util.Enumeration;
  +import java.util.HashMap;
  +import java.util.jar.JarEntry;
  +import java.util.jar.JarFile;
   import javax.servlet.ServletContext;
   import javax.servlet.ServletException;
   import javax.servlet.http.HttpServletRequest;
   import javax.servlet.http.HttpServletResponse;
   import org.apache.catalina.Container;
   import org.apache.catalina.Context;
  +import org.apache.catalina.Deployer;
   import org.apache.catalina.HttpRequest;
   import org.apache.catalina.Host;
  +import org.apache.catalina.Lifecycle;
  +import org.apache.catalina.LifecycleListener;
   import org.apache.catalina.Request;
   import org.apache.catalina.Response;
   
  @@ -84,12 +97,12 @@
    * requests directed to a particular web application.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.2 $ $Date: 2000/08/12 18:57:29 $
  + * @version $Revision: 1.3 $ $Date: 2000/10/04 23:03:04 $
    */
   
   public final class StandardHost
       extends ContainerBase
  -    implements Host {
  +    implements Deployer, Host {
   
   
       // ----------------------------------------------------------- Constructors
  @@ -122,6 +135,31 @@
   
   
       /**
  +     * The Java class name of the default context configuration class
  +     * for deployed web applications.
  +     */
  +    private String configClass =
  +        "org.apache.catalina.startup.ContextConfig";
  +
  +
  +    /**
  +     * The Java class name of the default Context implementation class for
  +     * deployed web applications.
  +     */
  +    private String contextClass =
  +        "org.apache.catalina.core.StandardContext";
  +
  +
  +    /**
  +     * The set of absolute pathnames to directories that were expanded
  +     * from WAR files, keyed by context path.  These entries may be used
  +     * to indicate that the expanded directory is to be removed when the
  +     * application is undeployed.
  +     */
  +    private HashMap expanded = new HashMap();
  +
  +
  +    /**
        * The descriptive information string for this implementation.
        */
       private static final String info =
  @@ -165,6 +203,60 @@
   
   
       /**
  +     * Return the Java class name of the context configuration class
  +     * for new web applications.
  +     */
  +    public String getConfigClass() {
  +
  +        return (this.configClass);
  +
  +    }
  +
  +
  +    /**
  +     * Set the Java class name of the context configuration class
  +     * for new web applications.
  +     *
  +     * @param configClass The new context configuration class
  +     */
  +    public void setConfigClass(String configClass) {
  +
  +        String oldConfigClass = this.configClass;
  +        this.configClass = configClass;
  +        support.firePropertyChange("configClass",
  +                                   oldConfigClass, this.configClass);
  +
  +    }
  +
  +
  +    /**
  +     * Return the Java class name of the Context implementation class
  +     * for new web applications.
  +     */
  +    public String getContextClass() {
  +
  +        return (this.contextClass);
  +
  +    }
  +
  +
  +    /**
  +     * Set the Java class name of the Context implementation class
  +     * for new web applications.
  +     *
  +     * @param contextClass The new context implementation class
  +     */
  +    public void setContextClass(String contextClass) {
  +
  +        String oldContextClass = this.contextClass;
  +        this.contextClass = contextClass;
  +        support.firePropertyChange("contextClass",
  +                                   oldContextClass, this.contextClass);
  +
  +    }
  +
  +
  +    /**
        * Return the canonical, fully qualified, name of the virtual host
        * this Container represents.
        */
  @@ -372,6 +464,188 @@
       }
   
   
  +    // ------------------------------------------------------- Deployer Methods
  +
  +
  +    /**
  +     * Deploy a new web application, whose web application archive is at the
  +     * specified URL, into this container with the specified context path.
  +     * A context path of "" (the empty string) should be used for the root
  +     * application for this container.  Otherwise, the context path must
  +     * start with a slash.
  +     * <p>
  +     * If this application is successfully deployed, a ContainerEvent of type
  +     * <code>DEPLOY_EVENT</code> will be sent to all registered listeners,
  +     * with the newly created <code>Context</code> as an argument.
  +     *
  +     * @param contextPath The context path to which this application should
  +     *  be deployed (must be unique)
  +     * @param war A URL of type "jar:" that points to a WAR file, or type
  +     *  "file:" that points to an unpacked directory structure containing
  +     *  the web application to be deployed
  +     *
  +     * @exception IllegalArgumentException if the specified context path
  +     *  is malformed (it must be "" or start with a slash)
  +     * @exception IllegalArgumentException if the specified context path
  +     *  is already attached to an existing web application
  +     * @exception IOException if an input/output error was encountered
  +     *  during deployment
  +     */
  +    public void deploy(String contextPath, URL war) throws IOException {
  +
  +        // Validate the format and state of our arguments
  +        if (contextPath == null)
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.pathRequired"));
  +        if (!contextPath.equals("") && !contextPath.startsWith("/"))
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.pathFormat", contextPath));
  +        if (findDeployedApp(contextPath) != null)
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.pathUsed", contextPath));
  +        if (war == null)
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.warRequired"));
  +
  +        // Prepare the local variables we will require
  +        String url = war.toString();
  +        String docBase = null;
  +        log(sm.getString("standardHost.deploying", contextPath, url));
  +
  +        // Expand a WAR archive into an unpacked directory if needed
  +        if (url.startsWith("jar:"))
  +            docBase = expand(war);
  +        else if (url.startsWith("file://"))
  +            docBase = url.substring(7);
  +        else if (url.startsWith("file:"))
  +            docBase = url.substring(5);
  +        else
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.warURL", url));
  +
  +        // Make sure the document base directory exists and is readable
  +        File docBaseDir = new File(docBase);
  +        if (!docBaseDir.exists() || !docBaseDir.isDirectory() ||
  +            !docBaseDir.canRead())
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.accessBase", docBase));
  +
  +        // Deploy this new web application
  +        try {
  +            Class clazz = Class.forName(contextClass);
  +            Context context = (Context) clazz.newInstance();
  +            context.setPath(contextPath);
  +            context.setDocBase(docBase);
  +            if (context instanceof Lifecycle) {
  +                clazz = Class.forName(configClass);
  +                LifecycleListener listener =
  +                    (LifecycleListener) clazz.newInstance();
  +                ((Lifecycle) context).addLifecycleListener(listener);
  +            }
  +            addChild(context);
  +	    fireContainerEvent(DEPLOY_EVENT, context);
  +            if (url.startsWith("jar:")) {
  +                synchronized (expanded) {
  +                    if (debug >= 1)
  +                        log("Recording expanded app at path " + contextPath);
  +                    expanded.put(contextPath, docBase);
  +                }
  +            }
  +        } catch (Exception e) {
  +            log(sm.getString("standardHost.deployError", contextPath), e);
  +            throw new IOException(e.toString());
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Return the Context for the deployed application that is associated
  +     * with the specified context path (if any); otherwise return
  +     * <code>null</code>.
  +     *
  +     * @param contextPath The context path of the requested web application
  +     */
  +    public Context findDeployedApp(String contextPath) {
  +
  +        if (name == null)
  +            return (null);
  +        synchronized (children) {
  +            return ((Context) children.get(contextPath));
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Return the context paths of all deployed web applications in this
  +     * Container.  If there are no deployed applications, a zero-length
  +     * array is returned.
  +     */
  +    public String[] findDeployedApps() {
  +
  +        synchronized (children) {
  +            String results[] = new String[children.size()];
  +            return ((String[]) children.keySet().toArray(results));
  +
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * Undeploy an existing web application, attached to the specified context
  +     * path.  If this application is successfully undeployed, a
  +     * ContainerEvent of type <code>UNDEPLOY_EVENT</code> will be sent to all
  +     * registered listeners, with the undeployed <code>Context</code> as
  +     * an argument.
  +     *
  +     * @param contextPath The context path of the application to be undeployed
  +     *
  +     * @exception IllegalArgumentException if the specified context path
  +     *  is malformed (it must be "" or start with a slash)
  +     * @exception IllegalArgumentException if the specified context path does
  +     *  not identify a currently deployed web application
  +     * @exception IOException if an input/output error occurs during
  +     *  undeployment
  +     */
  +    public void undeploy(String contextPath) throws IOException {
  +
  +        // Validate the format and state of our arguments
  +        if (contextPath == null)
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.pathRequired"));
  +        if (!contextPath.equals("") && !contextPath.startsWith("/"))
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.pathFormat", contextPath));
  +        Context context = findDeployedApp(contextPath);
  +        if (context == null)
  +            throw new IllegalArgumentException
  +                (sm.getString("standardHost.pathMissing", contextPath));
  +
  +        // Undeploy this web application
  +        log(sm.getString("standardHost.undeploying", contextPath));
  +        try {
  +            removeChild(context);
  +        } catch (Exception e) {
  +            log(sm.getString("standardHost.undeployError", contextPath), e);
  +            throw new IOException(e.toString());
  +        }
  +
  +        // Remove the expanded directory if we created one
  +        synchronized (expanded) {
  +            String docBase = (String) expanded.get(contextPath);
  +            if (docBase != null) {
  +                if (debug >= 1)
  +                    log("Removing expanded directory " + docBase);
  +                expanded.remove(contextPath);
  +                remove(new File(docBase));
  +            }
  +        }
  +
  +    }
  +
  +
       // -------------------------------------------------------- Private Methods
   
   
  @@ -384,6 +658,137 @@
       protected void addDefaultMapper(String mapperClass) {
   
   	super.addDefaultMapper(this.mapperClass);
  +
  +    }
  +
  +
  +    /**
  +     * 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 {
  +
  +        // Calculate the directory name of the expanded directory
  +        if (debug >= 1)
  +            log("expand(" + war.toString() + ")");
  +        String pathname = war.toString();
  +        if (pathname.endsWith("!/"))
  +            pathname = pathname.substring(0, pathname.length() - 2);
  +        int period = pathname.lastIndexOf(".");
  +        if (period >= pathname.length() - 4)
  +            pathname = pathname.substring(0, period);
  +        int slash = pathname.lastIndexOf("/");
  +        if (slash >= 0)
  +            pathname = pathname.substring(slash + 1);
  +        if (debug >= 1)
  +            log("  Proposed directory name: " + pathname);
  +
  +        // Make sure that there is no such directory already existing
  +        File appBase = new File(getAppBase());
  +        if (!appBase.isAbsolute())
  +            appBase = new File(System.getProperty("catalina.home"),
  +                               getAppBase());
  +        if (!appBase.exists() || !appBase.isDirectory())
  +            throw new IOException
  +                (sm.getString("standardHost.appBase",
  +                              appBase.getAbsolutePath()));
  +        File docBase = new File(appBase, pathname);
  +        if (docBase.exists())
  +            throw new IOException
  +                (sm.getString("standardHost.docBase",
  +                              docBase.getAbsolutePath()));
  +        docBase.mkdir();
  +
  +        // Expand the WAR into the new document base directory
  +        JarFile jarFile =
  +            ((JarURLConnection) war.openConnection()).getJarFile();
  +        Enumeration jarEntries = jarFile.entries();
  +        while (jarEntries.hasMoreElements()) {
  +            JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
  +            String name = jarEntry.getName();
  +            int last = name.lastIndexOf("/");
  +            if (last >= 0) {
  +                File parent = new File(docBase,
  +                                       name.substring(0, last));
  +                if (debug >= 2)
  +                    log("  Creating parent directory " + parent);
  +                parent.mkdirs();
  +            }
  +            if (name.endsWith("/"))
  +                continue;
  +            if (debug >= 2)
  +                log("  Creating expanded file " + name);
  +            InputStream input = jarFile.getInputStream(jarEntry);
  +            expand(input, docBase, name);
  +        }
  +        jarFile.close();
  +
  +        // Return the absolute path to our new document base directory
  +        return (docBase.getAbsolutePath());
  +
  +    }
  +
  +
  +    /**
  +     * 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 {
  +
  +        File file = new File(docBase, name);
  +        BufferedOutputStream output =
  +            new BufferedOutputStream(new FileOutputStream(file));
  +        byte buffer[] = new byte[2048];
  +        while (true) {
  +            int n = input.read(buffer);
  +            if (n <= 0)
  +                break;
  +            output.write(buffer, 0, n);
  +        }
  +        output.close();
  +        input.close();
  +
  +    }
  +
  +
  +    /**
  +     * Remove the specified directory and all of its contents.
  +     *
  +     * @param dir Directory to be removed
  +     *
  +     * @exception IOException if an input/output error occurs
  +     */
  +    protected void remove(File dir) throws IOException {
  +
  +        String list[] = dir.list();
  +        for (int i = 0; i < list.length; i++) {
  +            File file = new File(dir, list[i]);
  +            if (file.isDirectory()) {
  +                remove(file);
  +            } else {
  +                if (!file.delete())
  +                    throw new IOException("Cannot delete file " +
  +                                          file.getAbsolutePath());
  +            }
  +        }
  +        if (!dir.delete())
  +            throw new IOException("Cannot delete directory " +
  +                                  dir.getAbsolutePath());
   
       }
   
  
  
  
  1.2       +106 -153  jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup/HostConfig.java
  
  Index: HostConfig.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup/HostConfig.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HostConfig.java	2000/08/11 23:38:41	1.1
  +++ HostConfig.java	2000/10/04 23:03:05	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup/HostConfig.java,v
1.1 2000/08/11 23:38:41 craigmcc Exp $
  - * $Revision: 1.1 $
  - * $Date: 2000/08/11 23:38:41 $
  + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup/HostConfig.java,v
1.2 2000/10/04 23:03:05 craigmcc Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/10/04 23:03:05 $
    *
    * ====================================================================
    *
  @@ -79,6 +79,7 @@
   import java.util.jar.JarEntry;
   import java.util.jar.JarFile;
   import org.apache.catalina.Context;
  +import org.apache.catalina.Deployer;
   import org.apache.catalina.Host;
   import org.apache.catalina.Lifecycle;
   import org.apache.catalina.LifecycleEvent;
  @@ -92,7 +93,7 @@
    * of that Host, and the associated defined contexts.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.1 $ $Date: 2000/08/11 23:38:41 $
  + * @version $Revision: 1.2 $ $Date: 2000/10/04 23:03:05 $
    */
   
   public final class HostConfig
  @@ -248,161 +249,87 @@
   
   
       /**
  -     * Deploy any directories found in our "application root" directory that
  -     * look like they contain a web application.  For the purposes of this
  -     * method, the directory must contain a WEB-INF subdirectory that contains
  -     * a web application deployment descriptor file (<code>web.xml</code>).
  +     * Deploy applications for any directories or WAR files that are found
  +     * in our "application root" directory.
        */
  -    private void deploy() {
  +    private void deployApps() {
   
  -	if (debug >= 1)
  -	    log(sm.getString("hostConfig.deploying"));
  -
  -	// Discover and deploy web application directories as necessary
  -	File appBase = appBase();
  -	if (!appBase.exists() || !appBase.isDirectory())
  -	    return;
  -	String files[] = appBase.list();
  +        if (!(host instanceof Deployer))
  +            return;
  +        if (debug >= 1)
  +            log(sm.getString("hostConfig.deploying"));
  +
  +        File appBase = appBase();
  +        if (!appBase.exists() || !appBase.isDirectory())
  +            return;
  +        String files[] = appBase.list();
  +
  +        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 (dir.isDirectory()) {
  +
  +                // Make sure there is an application deployment descriptor
  +                File webXml = new File(dir, "/WEB-INF/web.xml");
  +                if (!webXml.exists() || !webXml.isFile() ||
  +                    !webXml.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 (debug >= 1)
  +                    log(sm.getString("hostConfig.deployDir", files[i]));
  +                try {
  +                    URL url = new URL("file", null, dir.getAbsolutePath());
  +                    ((Deployer) host).deploy(contextPath, url);
  +                } catch (Throwable t) {
  +                    log(sm.getString("hostConfig.deployDir.error", files[i]),
  +                        t);
  +                }
  +
  +            } else if (files[i].toLowerCase().endsWith(".war")) {
  +
  +                // 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);
  +                if (contextPath.equals("/ROOT"))
  +                    contextPath = "";
  +                if (host.findChild(contextPath) != null)
  +                    continue;
  +
  +                // Deploy the application in this WAR file
  +                if (debug >= 1)
  +                    log(sm.getString("hostConfig.deployJar", files[i]));
  +                try {
  +                    URL url = new URL("file", null, dir.getAbsolutePath());
  +                    url = new URL("jar:" + url.toString() + "!/");
  +                    ((Deployer) host).deploy(contextPath, url);
  +                } catch (Throwable t) {
  +                    log(sm.getString("hostConfig.deployJar.error", files[i]),
  +                        t);
  +                }
   
  -	for (int i = 0; i < files.length; i++) {
  +            }
   
  -	    File dir = new File(appBase, files[i]);
  -	    if (!dir.isDirectory())
  -	        continue;
  -	    File webXml = new File(dir, "/WEB-INF/web.xml");
  -	    if (!webXml.exists() || !webXml.isFile() ||
  -	        !webXml.canRead())
  -	        continue;
  -	    String contextPath = "/" + files[i];
  -	    if (files[i].equals("ROOT"))
  -	        contextPath = "";
  -	    if (host.findChild(contextPath) != null)
  -	        continue;
  -
  -	    log(sm.getString("hostConfig.deploy", files[i]));
  -	    try {
  -		Class clazz = Class.forName(contextClass);
  -		Context context =
  -		  (Context) clazz.newInstance();
  -		context.setPath(contextPath);
  -		context.setDocBase(files[i]);
  -		if (context instanceof Lifecycle) {
  -		    clazz = Class.forName(configClass);
  -		    LifecycleListener listener =
  -		      (LifecycleListener) clazz.newInstance();
  -		    ((Lifecycle) context).addLifecycleListener(listener);
  -		}
  -		host.addChild(context);
  -	    } catch (Exception e) {
  -		log(sm.getString("hostConfig.deploy.error", files[i]), e);
  -	    }
  -
  -	}
  +        }
   
       }
   
   
  -    /**
  -     * Expand any JAR files found in our "application root" directory that
  -     * do not have a corresponding directory without the ".jar" extension.
  -     */
  -    private void expand() {
  -
  -	if (debug >= 1)
  -	    log(sm.getString("hostConfig.expanding"));
  -
  -	// Discover and expand WAR files as necessary
  -	File appBase = appBase();
  -	if (!appBase.exists() || !appBase.isDirectory())
  -	    return;
  -	String files[] = appBase.list();
  -
  -	for (int i = 0; i < files.length; i++) {
  -
  -	    // Is this file a WAR that needs to be expanded?
  -	    File file = new File(appBase, files[i]);
  -	    if (file.isDirectory())
  -		continue;
  -	    String filename = files[i].toLowerCase();
  -	    if (!filename.endsWith(".war"))
  -		continue;
  -
  -	    // Has this WAR been expanded previously?
  -	    File dir = new File(appBase,
  -				files[i].substring(0, files[i].length() - 4));
  -	    if (dir.exists())
  -		continue;
  -
  -	    log(sm.getString("hostConfig.expand", files[i]));
  -	    JarFile jarFile = null;
  -	    try {
  -		dir.mkdirs();
  -		jarFile = new JarFile(new File(appBase, files[i]));
  -		Enumeration jarEntries = jarFile.entries();
  -		while (jarEntries.hasMoreElements()) {
  -		    JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
  -		    String name = jarEntry.getName();
  -		    int slash = name.lastIndexOf("/");
  -		    if (slash >= 0) {
  -			File parent = new File(dir,
  -					       name.substring(0, slash));
  -			if (debug >= 2)
  -			    log(" Creating parent directory " + parent);
  -			parent.mkdirs();
  -		    }
  -		    if (name.endsWith("/"))
  -		        continue;
  -		    if (debug >= 2)
  -		        log(" Creating expanded file " + name);
  -		    InputStream input = jarFile.getInputStream(jarEntry);
  -		    expand(input, dir, name);
  -		}
  -	    } catch (Exception e) {
  -		log(sm.getString("hostConfig.expand.error", files[i]), e);
  -		if (jarFile != null) {
  -		    try {
  -			jarFile.close();
  -		    } catch (Exception f) {
  -			;
  -		    }
  -		}
  -	    }
  -
  -	}
  -
  -    }
  -
   
       /**
  -     * Expand the specified input stream into the specified directory, into
  -     * a file named from the specified relative filename path.
  -     *
  -     * @param input InputStream to be copied
  -     * @param directory Base directory into which the file is created
  -     * @param path Relative pathname of the file to be created
  -     *
  -     * @exception IOException if any processing exception occurs
  -     */
  -    private void expand(InputStream input, File directory, String path)
  -        throws IOException {
  -
  -	File file = new File(directory, path);
  -	BufferedOutputStream output =
  -	  new BufferedOutputStream(new FileOutputStream(file));
  -	byte buffer[] = new byte[2048];
  -	while (true) {
  -	    int n = input.read(buffer);
  -	    if (n <= 0)
  -	        break;
  -	    output.write(buffer, 0, n);
  -	}
  -	output.close();
  -	input.close();
  -
  -    }
  -
  -
  -    /**
        * Log a message on the Logger associated with our Host (if any)
        *
        * @param message Message to be logged
  @@ -450,11 +377,10 @@
        */
       private void start() {
   
  -	if (debug > 0)
  +	if (debug >= 1)
   	    log(sm.getString("hostConfig.start"));
   
  -	expand();
  -	deploy();
  +        deployApps();
   
       }
   
  @@ -464,8 +390,35 @@
        */
       private void stop() {
   
  -	if (debug > 0)
  +	if (debug >= 1)
   	    log(sm.getString("hostConfig.stop"));
  +
  +        undeployApps();
  +
  +    }
  +
  +
  +    /**
  +     * Undeploy all deployed applications.
  +     */
  +    private void undeployApps() {
  +
  +        if (!(host instanceof Deployer))
  +            return;
  +        if (debug >= 1)
  +            log(sm.getString("hostConfig.undeploying"));
  +
  +        String contextPaths[] = ((Deployer) host).findDeployedApps();
  +        for (int i = 0; i < contextPaths.length; i++) {
  +            if (debug >= 1)
  +                log(sm.getString("hostConfig.undeploy", contextPaths[i]));
  +            try {
  +                ((Deployer) host).undeploy(contextPaths[i]);
  +            } catch (Throwable t) {
  +                log(sm.getString("hostConfig.undeploy.error",
  +                                 contextPaths[i]), t);
  +            }
  +        }
   
       }
   
  
  
  
  1.8       +8 -1      jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup/LocalStrings.properties,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- LocalStrings.properties	2000/10/03 21:30:44	1.7
  +++ LocalStrings.properties	2000/10/04 23:03:05	1.8
  @@ -36,13 +36,20 @@
   engineConfig.stop=EngineConfig: Processing STOP
   hostConfig.cce=Lifecycle event data object {0} is not a Host
   hostConfig.deploy=Deploying web application directory {0}
  +hostConfig.deployDir=Deploying web application directory {0}
  +hostConfig.deployDir.error=Error deploying web application directory {0}
  +hostConfig.deployJar=Deploying web application archive {0}
  +hostConfig.deployJar.error=Error deploying web application archive {0}
   hostConfig.deploy.error=Exception while deploying web application directory {0}
  -hostConfig.deploying=Deploying discovered web application directories
  +hostConfig.deploying=Deploying discovered web applications
   hostConfig.expand=Expanding web application archive {0}
   hostConfig.expand.error=Exception while expanding web application archive {0}
   hostConfig.expanding=Expanding discovered web application archives
   hostConfig.start=HostConfig: Processing START
   hostConfig.stop=HostConfig: Processing STOP
  +hostConfig.undeploy=Undeploying web application at context path {0}
  +hostConfig.undeploy.error=Error undeploying web application at context path {0}
  +hostConfig.undeploying=Undeploying deployed web applications
   userConfig.database=Exception loading user database
   userConfig.deploy=Deploying web application for user {0}
   userConfig.error=Error deploying web application for user {0}
  
  
  

Mime
View raw message