Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » manager » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.manager;
   20   
   21   
   22   import java.io.BufferedOutputStream;
   23   import java.io.File;
   24   import java.io.FileInputStream;
   25   import java.io.FileOutputStream;
   26   import java.io.IOException;
   27   import java.io.PrintWriter;
   28   import java.util.Iterator;
   29   
   30   import javax.management.MBeanServer;
   31   import javax.management.ObjectName;
   32   import javax.naming.Binding;
   33   import javax.naming.InitialContext;
   34   import javax.naming.NamingEnumeration;
   35   import javax.naming.NamingException;
   36   import javax.servlet.ServletException;
   37   import javax.servlet.ServletInputStream;
   38   import javax.servlet.UnavailableException;
   39   import javax.servlet.http.HttpServlet;
   40   import javax.servlet.http.HttpServletRequest;
   41   import javax.servlet.http.HttpServletResponse;
   42   
   43   import org.apache.catalina.Container;
   44   import org.apache.catalina.ContainerServlet;
   45   import org.apache.catalina.Context;
   46   import org.apache.catalina.Engine;
   47   import org.apache.catalina.Globals;
   48   import org.apache.catalina.Host;
   49   import org.apache.catalina.Lifecycle;
   50   import org.apache.catalina.Manager;
   51   import org.apache.catalina.Role;
   52   import org.apache.catalina.Server;
   53   import org.apache.catalina.ServerFactory;
   54   import org.apache.catalina.Session;
   55   import org.apache.catalina.UserDatabase;
   56   import org.apache.catalina.Wrapper;
   57   import org.apache.catalina.core.StandardHost;
   58   import org.apache.catalina.core.StandardServer;
   59   import org.apache.catalina.util.RequestUtil;
   60   import org.apache.catalina.util.ServerInfo;
   61   import org.apache.catalina.util.StringManager;
   62   import org.apache.tomcat.util.modeler.Registry;
   63   
   64   
   65   /**
   66    * Servlet that enables remote management of the web applications installed
   67    * within the same virtual host as this web application is.  Normally, this
   68    * functionality will be protected by a security constraint in the web
   69    * application deployment descriptor.  However, this requirement can be
   70    * relaxed during testing.
   71    * <p>
   72    * This servlet examines the value returned by <code>getPathInfo()</code>
   73    * and related query parameters to determine what action is being requested.
   74    * The following actions and parameters (starting after the servlet path)
   75    * are supported:
   76    * <ul>
   77    * <li><b>/deploy?config={config-url}</b> - Install and start a new
   78    *     web application, based on the contents of the context configuration
   79    *     file found at the specified URL.  The <code>docBase</code> attribute
   80    *     of the context configuration file is used to locate the actual
   81    *     WAR or directory containing the application.</li>
   82    * <li><b>/deploy?config={config-url}&war={war-url}/</b> - Install and start
   83    *     a new web application, based on the contents of the context
   84    *     configuration file found at <code>{config-url}</code>, overriding the
   85    *     <code>docBase</code> attribute with the contents of the web
   86    *     application archive found at <code>{war-url}</code>.</li>
   87    * <li><b>/deploy?path=/xxx&war={war-url}</b> - Install and start a new
   88    *     web application attached to context path <code>/xxx</code>, based
   89    *     on the contents of the web application archive found at the
   90    *     specified URL.</li>
   91    * <li><b>/list</b> - List the context paths of all currently installed web
   92    *     applications for this virtual host.  Each context will be listed with
   93    *     the following format <code>path:status:sessions</code>.
   94    *     Where path is the context path.  Status is either running or stopped.
   95    *     Sessions is the number of active Sessions.</li>
   96    * <li><b>/reload?path=/xxx</b> - Reload the Java classes and resources for
   97    *     the application at the specified path.</li>
   98    * <li><b>/resources?type=xxxx</b> - Enumerate the available global JNDI
   99    *     resources, optionally limited to those of the specified type
  100    *     (fully qualified Java class name), if available.</li>
  101    * <li><b>/roles</b> - Enumerate the available security role names and
  102    *     descriptions from the user database connected to the <code>users</code>
  103    *     resource reference.
  104    * <li><b>/serverinfo</b> - Display system OS and JVM properties.
  105    * <li><b>/sessions</b> - Deprecated. Use expire.
  106    * <li><b>/expire?path=/xxx</b> - List session idle timeinformation about the
  107    *     web application attached to context path <code>/xxx</code> for this
  108    *     virtual host.</li>
  109    * <li><b>/expire?path=/xxx&idle=mm</b> - Expire sessions
  110    *     for the context path <code>/xxx</code> which were idle for at
  111    *     least mm minutes.</li>
  112    * <li><b>/start?path=/xxx</b> - Start the web application attached to
  113    *     context path <code>/xxx</code> for this virtual host.</li>
  114    * <li><b>/stop?path=/xxx</b> - Stop the web application attached to
  115    *     context path <code>/xxx</code> for this virtual host.</li>
  116    * <li><b>/undeploy?path=/xxx</b> - Shutdown and remove the web application
  117    *     attached to context path <code>/xxx</code> for this virtual host,
  118    *     and remove the underlying WAR file or document base directory.
  119    *     (<em>NOTE</em> - This is only allowed if the WAR file or document
  120    *     base is stored in the <code>appBase</code> directory of this host,
  121    *     typically as a result of being placed there via the <code>/deploy</code>
  122    *     command.</li>
  123    * </ul>
  124    * <p>Use <code>path=/</code> for the ROOT context.</p>
  125    * <p>The syntax of the URL for a web application archive must conform to one
  126    * of the following patterns to be successfully deployed:</p>
  127    * <ul>
  128    * <li><b>file:/absolute/path/to/a/directory</b> - You can specify the absolute
  129    *     path of a directory that contains the unpacked version of a web
  130    *     application.  This directory will be attached to the context path you
  131    *     specify without any changes.</li>
  132    * <li><b>jar:file:/absolute/path/to/a/warfile.war!/</b> - You can specify a
  133    *     URL to a local web application archive file.  The syntax must conform to
  134    *     the rules specified by the <code>JarURLConnection</code> class for a
  135    *     reference to an entire JAR file.</li>
  136    * <li><b>jar:http://hostname:port/path/to/a/warfile.war!/</b> - You can specify
  137    *     a URL to a remote (HTTP-accessible) web application archive file.  The
  138    *     syntax must conform to the rules specified by the
  139    *     <code>JarURLConnection</code> class for a reference to an entire
  140    *     JAR file.</li>
  141    * </ul>
  142    * <p>
  143    * <b>NOTE</b> - Attempting to reload or remove the application containing
  144    * this servlet itself will not succeed.  Therefore, this servlet should
  145    * generally be deployed as a separate web application within the virtual host
  146    * to be managed.
  147    * <p>
  148    * <b>NOTE</b> - For security reasons, this application will not operate
  149    * when accessed via the invoker servlet.  You must explicitly map this servlet
  150    * with a servlet mapping, and you will always want to protect it with
  151    * appropriate security constraints as well.
  152    * <p>
  153    * The following servlet initialization parameters are recognized:
  154    * <ul>
  155    * <li><b>debug</b> - The debugging detail level that controls the amount
  156    *     of information that is logged by this servlet.  Default is zero.
  157    * </ul>
  158    *
  159    * @author Craig R. McClanahan
  160    * @author Remy Maucherat
  161    * @version $Revision: 915603 $ $Date: 2010-02-24 01:07:06 +0100 (Wed, 24 Feb 2010) $
  162    */
  163   
  164   public class ManagerServlet
  165       extends HttpServlet implements ContainerServlet {
  166   
  167   
  168       // ----------------------------------------------------- Instance Variables
  169   
  170   
  171       /**
  172        * Path where context descriptors should be deployed.
  173        */
  174       protected File configBase = null;
  175   
  176   
  177       /**
  178        * The Context container associated with our web application.
  179        */
  180       protected Context context = null;
  181   
  182   
  183       /**
  184        * The debugging detail level for this servlet.
  185        */
  186       protected int debug = 1;
  187   
  188   
  189       /**
  190        * File object representing the directory into which the deploy() command
  191        * will store the WAR and context configuration files that have been
  192        * uploaded.
  193        */
  194       protected File deployed = null;
  195   
  196   
  197       /**
  198        * Path used to store revisions of webapps.
  199        */
  200       protected File versioned = null;
  201   
  202   
  203       /**
  204        * Path used to store context descriptors.
  205        */
  206       protected File contextDescriptors = null;
  207   
  208   
  209       /**
  210        * The associated host.
  211        */
  212       protected Host host = null;
  213   
  214       
  215       /**
  216        * The host appBase.
  217        */
  218       protected File appBase = null;
  219       
  220       
  221       /**
  222        * MBean server.
  223        */
  224       protected MBeanServer mBeanServer = null;
  225   
  226   
  227       /**
  228        * The associated deployer ObjectName.
  229        */
  230       protected ObjectName oname = null;
  231       
  232   
  233       /**
  234        * The global JNDI <code>NamingContext</code> for this server,
  235        * if available.
  236        */
  237       protected javax.naming.Context global = null;
  238   
  239   
  240       /**
  241        * The string manager for this package.
  242        */
  243       protected static StringManager sm =
  244           StringManager.getManager(Constants.Package);
  245   
  246   
  247       /**
  248        * The Wrapper container associated with this servlet.
  249        */
  250       protected Wrapper wrapper = null;
  251   
  252   
  253       // ----------------------------------------------- ContainerServlet Methods
  254   
  255   
  256       /**
  257        * Return the Wrapper with which we are associated.
  258        */
  259       public Wrapper getWrapper() {
  260   
  261           return (this.wrapper);
  262   
  263       }
  264   
  265   
  266       /**
  267        * Set the Wrapper with which we are associated.
  268        *
  269        * @param wrapper The new wrapper
  270        */
  271       public void setWrapper(Wrapper wrapper) {
  272   
  273           this.wrapper = wrapper;
  274           if (wrapper == null) {
  275               context = null;
  276               host = null;
  277               oname = null;
  278           } else {
  279               context = (Context) wrapper.getParent();
  280               host = (Host) context.getParent();
  281               Engine engine = (Engine) host.getParent();
  282               try {
  283                   oname = new ObjectName(engine.getName() 
  284                           + ":type=Deployer,host=" + host.getName());
  285               } catch (Exception e) {
  286                   // ?
  287               }
  288           }
  289   
  290           // Retrieve the MBean server
  291           mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
  292           
  293       }
  294   
  295   
  296       // --------------------------------------------------------- Public Methods
  297   
  298   
  299       /**
  300        * Finalize this servlet.
  301        */
  302       public void destroy() {
  303   
  304           ;       // No actions necessary
  305   
  306       }
  307   
  308   
  309       /**
  310        * Process a GET request for the specified resource.
  311        *
  312        * @param request The servlet request we are processing
  313        * @param response The servlet response we are creating
  314        *
  315        * @exception IOException if an input/output error occurs
  316        * @exception ServletException if a servlet-specified error occurs
  317        */
  318       public void doGet(HttpServletRequest request,
  319                         HttpServletResponse response)
  320           throws IOException, ServletException {
  321   
  322           // Verify that we were not accessed using the invoker servlet
  323           if (request.getAttribute(Globals.INVOKED_ATTR) != null)
  324               throw new UnavailableException
  325                   (sm.getString("managerServlet.cannotInvoke"));
  326   
  327           // Identify the request parameters that we need
  328           String command = request.getPathInfo();
  329           if (command == null)
  330               command = request.getServletPath();
  331           String config = request.getParameter("config");
  332           String path = request.getParameter("path");
  333           String type = request.getParameter("type");
  334           String war = request.getParameter("war");
  335           String tag = request.getParameter("tag");
  336           boolean update = false;
  337           if ((request.getParameter("update") != null) 
  338               && (request.getParameter("update").equals("true"))) {
  339               update = true;
  340           }
  341   
  342           // Prepare our output writer to generate the response message
  343           response.setContentType("text/plain; charset=" + Constants.CHARSET);
  344           PrintWriter writer = response.getWriter();
  345   
  346           // Process the requested command (note - "/deploy" is not listed here)
  347           if (command == null) {
  348               writer.println(sm.getString("managerServlet.noCommand"));
  349           } else if (command.equals("/deploy")) {
  350               if (war != null || config != null) {
  351                   deploy(writer, config, path, war, update);
  352               } else {
  353                   deploy(writer, path, tag);
  354               }
  355           } else if (command.equals("/install")) {
  356               // Deprecated
  357               deploy(writer, config, path, war, false);
  358           } else if (command.equals("/list")) {
  359               list(writer);
  360           } else if (command.equals("/reload")) {
  361               reload(writer, path);
  362           } else if (command.equals("/remove")) {
  363               // Deprecated
  364               undeploy(writer, path);
  365           } else if (command.equals("/resources")) {
  366               resources(writer, type);
  367           } else if (command.equals("/roles")) {
  368               roles(writer);
  369           } else if (command.equals("/save")) {
  370               save(writer, path);
  371           } else if (command.equals("/serverinfo")) {
  372               serverinfo(writer);
  373           } else if (command.equals("/sessions")) {
  374               expireSessions(writer, path, request);
  375           } else if (command.equals("/expire")) {
  376               expireSessions(writer, path, request);
  377           } else if (command.equals("/start")) {
  378               start(writer, path);
  379           } else if (command.equals("/stop")) {
  380               stop(writer, path);
  381           } else if (command.equals("/undeploy")) {
  382               undeploy(writer, path);
  383           } else if (command.equals("/findleaks")) {
  384               findleaks(writer);
  385           } else {
  386               writer.println(sm.getString("managerServlet.unknownCommand",
  387                                           command));
  388           }
  389   
  390           // Finish up the response
  391           writer.flush();
  392           writer.close();
  393   
  394       }
  395   
  396   
  397       /**
  398        * Process a PUT request for the specified resource.
  399        *
  400        * @param request The servlet request we are processing
  401        * @param response The servlet response we are creating
  402        *
  403        * @exception IOException if an input/output error occurs
  404        * @exception ServletException if a servlet-specified error occurs
  405        */
  406       public void doPut(HttpServletRequest request,
  407                         HttpServletResponse response)
  408           throws IOException, ServletException {
  409   
  410           // Verify that we were not accessed using the invoker servlet
  411           if (request.getAttribute(Globals.INVOKED_ATTR) != null)
  412               throw new UnavailableException
  413                   (sm.getString("managerServlet.cannotInvoke"));
  414   
  415           // Identify the request parameters that we need
  416           String command = request.getPathInfo();
  417           if (command == null)
  418               command = request.getServletPath();
  419           String path = request.getParameter("path");
  420           String tag = request.getParameter("tag");
  421           boolean update = false;
  422           if ((request.getParameter("update") != null) 
  423               && (request.getParameter("update").equals("true"))) {
  424               update = true;
  425           }
  426   
  427           // Prepare our output writer to generate the response message
  428           response.setContentType("text/plain;charset="+Constants.CHARSET);
  429           PrintWriter writer = response.getWriter();
  430   
  431           // Process the requested command
  432           if (command == null) {
  433               writer.println(sm.getString("managerServlet.noCommand"));
  434           } else if (command.equals("/deploy")) {
  435               deploy(writer, path, tag, update, request);
  436           } else {
  437               writer.println(sm.getString("managerServlet.unknownCommand",
  438                                           command));
  439           }
  440   
  441           // Finish up the response
  442           writer.flush();
  443           writer.close();
  444   
  445       }
  446   
  447   
  448       /**
  449        * Initialize this servlet.
  450        */
  451       public void init() throws ServletException {
  452   
  453           // Ensure that our ContainerServlet properties have been set
  454           if ((wrapper == null) || (context == null))
  455               throw new UnavailableException
  456                   (sm.getString("managerServlet.noWrapper"));
  457   
  458           // Verify that we were not accessed using the invoker servlet
  459           String servletName = getServletConfig().getServletName();
  460           if (servletName == null)
  461               servletName = "";
  462           if (servletName.startsWith("org.apache.catalina.INVOKER."))
  463               throw new UnavailableException
  464                   (sm.getString("managerServlet.cannotInvoke"));
  465   
  466           // Set our properties from the initialization parameters
  467           String value = null;
  468           try {
  469               value = getServletConfig().getInitParameter("debug");
  470               debug = Integer.parseInt(value);
  471           } catch (Throwable t) {
  472               ;
  473           }
  474   
  475           // Acquire global JNDI resources if available
  476           Server server = ServerFactory.getServer();
  477           if ((server != null) && (server instanceof StandardServer)) {
  478               global = ((StandardServer) server).getGlobalNamingContext();
  479           }
  480   
  481           // Calculate the directory into which we will be deploying applications
  482           versioned = (File) getServletContext().getAttribute
  483               ("javax.servlet.context.tempdir");
  484   
  485           // Identify the appBase of the owning Host of this Context
  486           // (if any)
  487           String appBase = ((Host) context.getParent()).getAppBase();
  488           deployed = new File(appBase);
  489           if (!deployed.isAbsolute()) {
  490               deployed = new File(System.getProperty("catalina.base"),
  491                                   appBase);
  492           }
  493           configBase = new File(System.getProperty("catalina.base"), "conf");
  494           Container container = context;
  495           Container host = null;
  496           Container engine = null;
  497           while (container != null) {
  498               if (container instanceof Host)
  499                   host = container;
  500               if (container instanceof Engine)
  501                   engine = container;
  502               container = container.getParent();
  503           }
  504           if (engine != null) {
  505               configBase = new File(configBase, engine.getName());
  506           }
  507           if (host != null) {
  508               configBase = new File(configBase, host.getName());
  509           }
  510           // Note: The directory must exist for this to work.
  511   
  512           // Log debugging messages as necessary
  513           if (debug >= 1) {
  514               log("init: Associated with Deployer '" +
  515                   oname + "'");
  516               if (global != null) {
  517                   log("init: Global resources are available");
  518               }
  519           }
  520   
  521       }
  522   
  523   
  524   
  525       // -------------------------------------------------------- Private Methods
  526   
  527   
  528       /**
  529        * Find potential memory leaks caused by web application reload.
  530        */
  531       protected void findleaks(PrintWriter writer) {
  532           
  533           if (!(host instanceof StandardHost)) {
  534               writer.println(sm.getString("managerServlet.findleaksFail"));
  535               return;
  536           }
  537           
  538           String[] results =
  539               ((StandardHost) host).findReloadedContextMemoryLeaks();
  540           
  541           for (String result : results) {
  542               if ("".equals(result)) {
  543                   result = "/";
  544               }
  545               writer.println(result);
  546           }
  547       }
  548       
  549       
  550       /**
  551        * Store server configuration.
  552        * 
  553        * @param path Optional context path to save
  554        */
  555       protected synchronized void save(PrintWriter writer, String path) {
  556   
  557           Server server = ServerFactory.getServer();
  558   
  559           if (!(server instanceof StandardServer)) {
  560               writer.println(sm.getString("managerServlet.saveFail", server));
  561               return;
  562           }
  563   
  564           if ((path == null) || path.length() == 0 || !path.startsWith("/")) {
  565               try {
  566                   ((StandardServer) server).storeConfig();
  567                   writer.println(sm.getString("managerServlet.saved"));
  568               } catch (Exception e) {
  569                   log("managerServlet.storeConfig", e);
  570                   writer.println(sm.getString("managerServlet.exception",
  571                                               e.toString()));
  572                   return;
  573               }
  574           } else {
  575               String contextPath = path;
  576               if (path.equals("/")) {
  577                   contextPath = "";
  578               }
  579               Context context = (Context) host.findChild(contextPath);
  580               if (context == null) {
  581                   writer.println(sm.getString("managerServlet.noContext", path));
  582                   return;
  583               }
  584               try {
  585                   ((StandardServer) server).storeContext(context);
  586                   writer.println(sm.getString("managerServlet.savedContext", 
  587                                  path));
  588               } catch (Exception e) {
  589                   log("managerServlet.save[" + path + "]", e);
  590                   writer.println(sm.getString("managerServlet.exception",
  591                                               e.toString()));
  592                   return;
  593               }
  594           }
  595   
  596       }
  597   
  598   
  599       /**
  600        * Deploy a web application archive (included in the current request)
  601        * at the specified context path.
  602        *
  603        * @param writer Writer to render results to
  604        * @param path Context path of the application to be installed
  605        * @param tag Tag to be associated with the webapp
  606        * @param request Servlet request we are processing
  607        */
  608       protected synchronized void deploy
  609           (PrintWriter writer, String path,
  610            String tag, boolean update, HttpServletRequest request) {
  611   
  612           if (debug >= 1) {
  613               log("deploy: Deploying web application at '" + path + "'");
  614           }
  615   
  616           // Validate the requested context path
  617           if ((path == null) || path.length() == 0 || !path.startsWith("/")) {
  618               writer.println(sm.getString("managerServlet.invalidPath", path));
  619               return;
  620           }
  621           String displayPath = path;
  622           if( path.equals("/") )
  623               path = "";
  624           String basename = getDocBase(path);
  625   
  626           // Check if app already exists, or undeploy it if updating
  627           Context context = (Context) host.findChild(path);
  628           if (update) {
  629               if (context != null) {
  630                   undeploy(writer, displayPath);
  631               }
  632               context = (Context) host.findChild(path);
  633           }
  634           if (context != null) {
  635               writer.println
  636                   (sm.getString("managerServlet.alreadyContext",
  637                                 displayPath));
  638               return;
  639           }
  640   
  641           // Calculate the base path
  642           File deployedPath = deployed;
  643           if (tag != null) {
  644               deployedPath = new File(versioned, tag);
  645               deployedPath.mkdirs();
  646           }
  647   
  648           // Upload the web application archive to a local WAR file
  649           File localWar = new File(deployedPath, basename + ".war");
  650           if (debug >= 2) {
  651               log("Uploading WAR file to " + localWar);
  652           }
  653   
  654           // Copy WAR to appBase
  655           try {
  656               if (!isServiced(path)) {
  657                   addServiced(path);
  658                   try {
  659                       // Upload WAR
  660                       uploadWar(request, localWar);
  661                       // Copy WAR and XML to the host app base if needed
  662                       if (tag != null) {
  663                           deployedPath = deployed;
  664                           File localWarCopy = new File(deployedPath, basename + ".war");
  665                           copy(localWar, localWarCopy);
  666                           localWar = localWarCopy;
  667                           copy(localWar, new File(getAppBase(), basename + ".war"));
  668                       }
  669                       // Perform new deployment
  670                       check(path);
  671                   } finally {
  672                       removeServiced(path);
  673                   }
  674               }
  675           } catch (Exception e) {
  676               log("managerServlet.check[" + displayPath + "]", e);
  677               writer.println(sm.getString("managerServlet.exception",
  678                                           e.toString()));
  679               return;
  680           }
  681           
  682           context = (Context) host.findChild(path);
  683           if (context != null && context.getConfigured()) {
  684               writer.println(sm.getString("managerServlet.deployed", displayPath));
  685           } else {
  686               // Something failed
  687               writer.println(sm.getString("managerServlet.deployFailed", displayPath));
  688           }
  689           
  690       }
  691   
  692   
  693       /**
  694        * Install an application for the specified path from the specified
  695        * web application archive.
  696        *
  697        * @param writer Writer to render results to
  698        * @param tag Revision tag to deploy from
  699        * @param path Context path of the application to be installed
  700        */
  701       protected void deploy(PrintWriter writer, String path, String tag) {
  702   
  703           // Validate the requested context path
  704           if ((path == null) || path.length() == 0 || !path.startsWith("/")) {
  705               writer.println(sm.getString("managerServlet.invalidPath", path));
  706               return;
  707           }
  708           String displayPath = path;
  709           if( path.equals("/") )
  710               path = "";
  711   
  712           // Calculate the base path
  713           File deployedPath = versioned;
  714           if (tag != null) {
  715               deployedPath = new File(deployedPath, tag);
  716           }
  717   
  718           // Find the local WAR file
  719           File localWar = new File(deployedPath, getDocBase(path) + ".war");
  720           // Find the local context deployment file (if any)
  721           File localXml = new File(configBase, getConfigFile(path) + ".xml");
  722   
  723           // Check if app already exists, or undeploy it if updating
  724           Context context = (Context) host.findChild(path);
  725           if (context != null) {
  726               undeploy(writer, displayPath);
  727           }
  728   
  729           // Copy WAR to appBase
  730           try {
  731               if (!isServiced(path)) {
  732                   addServiced(path);
  733                   try {
  734                       copy(localWar, new File(getAppBase(), getDocBase(path) + ".war"));
  735                       // Perform new deployment
  736                       check(path);
  737                   } finally {
  738                       removeServiced(path);
  739                   }
  740               }
  741           } catch (Exception e) {
  742               log("managerServlet.check[" + displayPath + "]", e);
  743               writer.println(sm.getString("managerServlet.exception",
  744                                           e.toString()));
  745               return;
  746           }
  747           
  748           context = (Context) host.findChild(path);
  749           if (context != null && context.getConfigured()) {
  750               writer.println(sm.getString("managerServlet.deployed", displayPath));
  751           } else {
  752               // Something failed
  753               writer.println(sm.getString("managerServlet.deployFailed", displayPath));
  754           }
  755           
  756       }
  757   
  758   
  759       /**
  760        * Install an application for the specified path from the specified
  761        * web application archive.
  762        *
  763        * @param writer Writer to render results to
  764        * @param config URL of the context configuration file to be installed
  765        * @param path Context path of the application to be installed
  766        * @param war URL of the web application archive to be installed
  767        * @param update true to override any existing webapp on the path
  768        */
  769       protected void deploy(PrintWriter writer, String config,
  770               String path, String war, boolean update) {
  771           
  772           if (config != null && config.length() == 0) {
  773               config = null;
  774           }
  775           if (war != null && war.length() == 0) {
  776               war = null;
  777           }
  778           
  779           if (debug >= 1) {
  780               if (config != null && config.length() > 0) {
  781                   if (war != null) {
  782                       log("install: Installing context configuration at '" +
  783                               config + "' from '" + war + "'");
  784                   } else {
  785                       log("install: Installing context configuration at '" +
  786                               config + "'");
  787                   }
  788               } else {
  789                   if (path != null && path.length() > 0) {
  790                       log("install: Installing web application at '" + path +
  791                               "' from '" + war + "'");
  792                   } else {
  793                       log("install: Installing web application from '" + war + "'");
  794                   }
  795               }
  796           }
  797           
  798           if (path == null || path.length() == 0 || !path.startsWith("/")) {
  799               writer.println(sm.getString("managerServlet.invalidPath",
  800                                           RequestUtil.filter(path)));
  801               return;
  802           }
  803           String displayPath = path;
  804           if("/".equals(path)) {
  805               path = "";
  806           }
  807           
  808           // Check if app already exists, or undeploy it if updating
  809           Context context = (Context) host.findChild(path);
  810           if (update) {
  811               if (context != null) {
  812                   undeploy(writer, displayPath);
  813               }
  814               context = (Context) host.findChild(path);
  815           }
  816           if (context != null) {
  817               writer.println
  818               (sm.getString("managerServlet.alreadyContext",
  819                       displayPath));
  820               return;
  821           }
  822           
  823           if (config != null && (config.startsWith("file:"))) {
  824               config = config.substring("file:".length());
  825           }
  826           if (war != null && (war.startsWith("file:"))) {
  827               war = war.substring("file:".length());
  828           }
  829           
  830           try {
  831               if (!isServiced(path)) {
  832                   addServiced(path);
  833                   try {
  834                       if (config != null) {
  835                           configBase.mkdirs();
  836                           copy(new File(config), 
  837                                   new File(configBase, getConfigFile(path) + ".xml"));
  838                       }
  839                       if (war != null) {
  840                           if (war.endsWith(".war")) {
  841                               copy(new File(war), 
  842                                       new File(getAppBase(), getDocBase(path) + ".war"));
  843                           } else {
  844                               copy(new File(war), 
  845                                       new File(getAppBase(), getDocBase(path)));
  846                           }
  847                       }
  848                       // Perform new deployment
  849                       check(path);
  850                   } finally {
  851                       removeServiced(path);
  852                   }
  853               }
  854               context = (Context) host.findChild(path);
  855               if (context != null && context.getConfigured() && context.getAvailable()) {
  856                   writer.println(sm.getString("managerServlet.deployed", displayPath));
  857               } else if (context!=null && !context.getAvailable()) {
  858                   writer.println(sm.getString("managerServlet.deployedButNotStarted", displayPath));
  859               } else {
  860                   // Something failed
  861                   writer.println(sm.getString("managerServlet.deployFailed", displayPath));
  862               }
  863           } catch (Throwable t) {
  864               log("ManagerServlet.install[" + displayPath + "]", t);
  865               writer.println(sm.getString("managerServlet.exception",
  866                       t.toString()));
  867           }
  868           
  869       }
  870   
  871   
  872       /**
  873        * Render a list of the currently active Contexts in our virtual host.
  874        *
  875        * @param writer Writer to render to
  876        */
  877       protected void list(PrintWriter writer) {
  878   
  879           if (debug >= 1)
  880               log("list: Listing contexts for virtual host '" +
  881                   host.getName() + "'");
  882   
  883           writer.println(sm.getString("managerServlet.listed",
  884                                       host.getName()));
  885           Container[] contexts = host.findChildren();
  886           for (int i = 0; i < contexts.length; i++) {
  887               Context context = (Context) contexts[i];
  888               String displayPath = context.getPath();
  889               if( displayPath.equals("") )
  890                   displayPath = "/";
  891               if (context != null ) {
  892                   if (context.getAvailable()) {
  893                       writer.println(sm.getString("managerServlet.listitem",
  894                                                   displayPath,
  895                                                   "running",
  896                                         "" + context.getManager().findSessions().length,
  897                                                   context.getDocBase()));
  898                   } else {
  899                       writer.println(sm.getString("managerServlet.listitem",
  900                                                   displayPath,
  901                                                   "stopped",
  902                                                   "0",
  903                                                   context.getDocBase()));
  904                   }
  905               }
  906           }
  907       }
  908   
  909   
  910       /**
  911        * Reload the web application at the specified context path.
  912        *
  913        * @param writer Writer to render to
  914        * @param path Context path of the application to be restarted
  915        */
  916       protected void reload(PrintWriter writer, String path) {
  917   
  918           if (debug >= 1)
  919               log("restart: Reloading web application at '" + path + "'");
  920   
  921           if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
  922               writer.println(sm.getString("managerServlet.invalidPath",
  923                                           RequestUtil.filter(path)));
  924               return;
  925           }
  926           String displayPath = path;
  927           if( path.equals("/") )
  928               path = "";
  929   
  930           try {
  931               Context context = (Context) host.findChild(path);
  932               if (context == null) {
  933                   writer.println(sm.getString
  934                                  ("managerServlet.noContext",
  935                                      RequestUtil.filter(displayPath)));
  936                   return;
  937               }
  938               // It isn't possible for the manager to reload itself
  939               if (context.getPath().equals(this.context.getPath())) {
  940                   writer.println(sm.getString("managerServlet.noSelf"));
  941                   return;
  942               }
  943               context.reload();
  944               writer.println
  945                   (sm.getString("managerServlet.reloaded", displayPath));
  946           } catch (Throwable t) {
  947               log("ManagerServlet.reload[" + displayPath + "]", t);
  948               writer.println(sm.getString("managerServlet.exception",
  949                                           t.toString()));
  950           }
  951   
  952       }
  953   
  954   
  955       /**
  956        * Render a list of available global JNDI resources.
  957        *
  958        * @param type Fully qualified class name of the resource type of interest,
  959        *  or <code>null</code> to list resources of all types
  960        */
  961       protected void resources(PrintWriter writer, String type) {
  962   
  963           if (debug >= 1) {
  964               if (type != null) {
  965                   log("resources:  Listing resources of type " + type);
  966               } else {
  967                   log("resources:  Listing resources of all types");
  968               }
  969           }
  970   
  971           // Is the global JNDI resources context available?
  972           if (global == null) {
  973               writer.println(sm.getString("managerServlet.noGlobal"));
  974               return;
  975           }
  976   
  977           // Enumerate the global JNDI resources of the requested type
  978           if (type != null) {
  979               writer.println(sm.getString("managerServlet.resourcesType",
  980                                           type));
  981           } else {
  982               writer.println(sm.getString("managerServlet.resourcesAll"));
  983           }
  984   
  985           Class clazz = null;
  986           try {
  987               if (type != null) {
  988                   clazz = Class.forName(type);
  989               }
  990           } catch (Throwable t) {
  991               log("ManagerServlet.resources[" + type + "]", t);
  992               writer.println(sm.getString("managerServlet.exception",
  993                                           t.toString()));
  994               return;
  995           }
  996   
  997           printResources(writer, "", global, type, clazz);
  998   
  999       }
 1000   
 1001   
 1002       /**
 1003        * List the resources of the given context.
 1004        */
 1005       protected void printResources(PrintWriter writer, String prefix,
 1006                                     javax.naming.Context namingContext,
 1007                                     String type, Class clazz) {
 1008   
 1009           try {
 1010               NamingEnumeration items = namingContext.listBindings("");
 1011               while (items.hasMore()) {
 1012                   Binding item = (Binding) items.next();
 1013                   if (item.getObject() instanceof javax.naming.Context) {
 1014                       printResources
 1015                           (writer, prefix + item.getName() + "/",
 1016                            (javax.naming.Context) item.getObject(), type, clazz);
 1017                   } else {
 1018                       if ((clazz != null) &&
 1019                           (!(clazz.isInstance(item.getObject())))) {
 1020                           continue;
 1021                       }
 1022                       writer.print(prefix + item.getName());
 1023                       writer.print(':');
 1024                       writer.print(item.getClassName());
 1025                       // Do we want a description if available?
 1026                       writer.println();
 1027                   }
 1028               }
 1029           } catch (Throwable t) {
 1030               log("ManagerServlet.resources[" + type + "]", t);
 1031               writer.println(sm.getString("managerServlet.exception",
 1032                                           t.toString()));
 1033           }
 1034   
 1035       }
 1036   
 1037   
 1038       /**
 1039        * Render a list of security role names (and corresponding descriptions)
 1040        * from the <code>org.apache.catalina.UserDatabase</code> resource that is
 1041        * connected to the <code>users</code> resource reference.  Typically, this
 1042        * will be the global user database, but can be adjusted if you have
 1043        * different user databases for different virtual hosts.
 1044        *
 1045        * @param writer Writer to render to
 1046        */
 1047       protected void roles(PrintWriter writer) {
 1048   
 1049           if (debug >= 1) {
 1050               log("roles:  List security roles from user database");
 1051           }
 1052   
 1053           // Look up the UserDatabase instance we should use
 1054           UserDatabase database = null;
 1055           try {
 1056               InitialContext ic = new InitialContext();
 1057               database = (UserDatabase) ic.lookup("java:comp/env/users");
 1058           } catch (NamingException e) {
 1059               writer.println(sm.getString("managerServlet.userDatabaseError"));
 1060               log("java:comp/env/users", e);
 1061               return;
 1062           }
 1063           if (database == null) {
 1064               writer.println(sm.getString("managerServlet.userDatabaseMissing"));
 1065               return;
 1066           }
 1067   
 1068           // Enumerate the available roles
 1069           writer.println(sm.getString("managerServlet.rolesList"));
 1070           Iterator roles = database.getRoles();
 1071           if (roles != null) {
 1072               while (roles.hasNext()) {
 1073                   Role role = (Role) roles.next();
 1074                   writer.print(role.getRolename());
 1075                   writer.print(':');
 1076                   if (role.getDescription() != null) {
 1077                       writer.print(role.getDescription());
 1078                   }
 1079                   writer.println();
 1080               }
 1081           }
 1082   
 1083   
 1084       }
 1085   
 1086   
 1087       /**
 1088        * Writes System OS and JVM properties.
 1089        * @param writer Writer to render to
 1090        */
 1091       protected void serverinfo(PrintWriter writer) {
 1092           if (debug >= 1)
 1093               log("serverinfo");
 1094           try {
 1095               StringBuffer props = new StringBuffer();
 1096               props.append("OK - Server info");
 1097               props.append("\nTomcat Version: ");
 1098               props.append(ServerInfo.getServerInfo());
 1099               props.append("\nOS Name: ");
 1100               props.append(System.getProperty("os.name"));
 1101               props.append("\nOS Version: ");
 1102               props.append(System.getProperty("os.version"));
 1103               props.append("\nOS Architecture: ");
 1104               props.append(System.getProperty("os.arch"));
 1105               props.append("\nJVM Version: ");
 1106               props.append(System.getProperty("java.runtime.version"));
 1107               props.append("\nJVM Vendor: ");
 1108               props.append(System.getProperty("java.vm.vendor"));
 1109               writer.println(props.toString());
 1110           } catch (Throwable t) {
 1111               getServletContext().log("ManagerServlet.serverinfo",t);
 1112               writer.println(sm.getString("managerServlet.exception",
 1113                                           t.toString()));
 1114           }
 1115       }
 1116   
 1117       /**
 1118        * Session information for the web application at the specified context path.
 1119        * Displays a profile of session lastAccessedTime listing number
 1120        * of sessions for each 10 minute interval up to 10 hours.
 1121        *
 1122        * @param writer Writer to render to
 1123        * @param path Context path of the application to list session information for
 1124        * @param idle Expire all sessions with idle time &ge; idle for this context
 1125        */
 1126       protected void sessions(PrintWriter writer, String path, int idle) {
 1127   
 1128           if (debug >= 1) {
 1129               log("sessions: Session information for web application at '" + path + "'");
 1130               if (idle >= 0)
 1131                   log("sessions: Session expiration for " + idle + " minutes '" + path + "'");
 1132           }
 1133   
 1134           if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
 1135               writer.println(sm.getString("managerServlet.invalidPath",
 1136                                           RequestUtil.filter(path)));
 1137               return;
 1138           }
 1139           String displayPath = path;
 1140           if( path.equals("/") )
 1141               path = "";
 1142           try {
 1143               Context context = (Context) host.findChild(path);
 1144               if (context == null) {
 1145                   writer.println(sm.getString("managerServlet.noContext",
 1146                                               RequestUtil.filter(displayPath)));
 1147                   return;
 1148               }
 1149               Manager manager = context.getManager() ;
 1150               if(manager == null) {
 1151                  writer.println(sm.getString("managerServlet.noManager",
 1152                  RequestUtil.filter(displayPath)));
 1153                  return;               
 1154               }
 1155               int maxCount = 60;
 1156               int maxInactiveInterval = manager.getMaxInactiveInterval()/60;
 1157               int histoInterval = maxInactiveInterval / maxCount;
 1158               if ( histoInterval * maxCount < maxInactiveInterval ) 
 1159                   histoInterval++;
 1160               if (0==histoInterval)
 1161                   histoInterval=1;
 1162               maxCount = maxInactiveInterval / histoInterval;
 1163               if ( histoInterval * maxCount < maxInactiveInterval ) 
 1164                   maxCount++;
 1165   
 1166               writer.println(sm.getString("managerServlet.sessions", displayPath));
 1167               writer.println(sm.getString("managerServlet.sessiondefaultmax",
 1168                                   "" + maxInactiveInterval));
 1169               Session [] sessions = manager.findSessions();
 1170               int [] timeout = new int[maxCount];
 1171               int notimeout = 0;
 1172               int expired = 0;
 1173               long now = System.currentTimeMillis();
 1174               for (int i = 0; i < sessions.length; i++) {
 1175                   int time = (int)((now-sessions[i].getLastAccessedTimeInternal())/1000);
 1176                   if (idle >= 0 && time >= idle*60) {
 1177                       sessions[i].expire();
 1178                       idle++;
 1179                   }
 1180                   time=time/60/histoInterval;
 1181                   if (time < 0)
 1182                       notimeout++;
 1183                   else if (time >= maxCount)
 1184                       timeout[maxCount-1]++;
 1185                   else
 1186                       timeout[time]++;
 1187               }
 1188               if (timeout[0] > 0)
 1189                   writer.println(sm.getString("managerServlet.sessiontimeout",
 1190                                               "<" + histoInterval, "" + timeout[0]));
 1191               for (int i = 1; i < maxCount-1; i++) {
 1192                   if (timeout[i] > 0)
 1193                       writer.println(sm.getString("managerServlet.sessiontimeout",
 1194                                        "" + (i)*histoInterval + " - <" + (i+1)*histoInterval,
 1195                                                   "" + timeout[i]));
 1196               }
 1197               if (timeout[maxCount-1] > 0)
 1198                   writer.println(sm.getString("managerServlet.sessiontimeout",
 1199                                               ">=" + maxCount*histoInterval,
 1200                                               "" + timeout[maxCount-1]));
 1201               if (notimeout > 0)
 1202                   writer.println(sm.getString("managerServlet.sessiontimeout",
 1203                                               "unlimited","" + notimeout));
 1204               if (idle >= 0)
 1205                   writer.println(sm.getString("managerServlet.sessiontimeout",
 1206                                               "" + idle,"expired " + expired));
 1207           } catch (Throwable t) {
 1208               log("ManagerServlet.sessions[" + displayPath + "]", t);
 1209               writer.println(sm.getString("managerServlet.exception",
 1210                                           t.toString()));
 1211           }
 1212   
 1213       }
 1214   
 1215   
 1216       /**
 1217        * Session information for the web application at the specified context path.
 1218        * Displays a profile of session lastAccessedTime listing number
 1219        * of sessions for each 10 minute interval up to 10 hours.
 1220        *
 1221        * @param writer Writer to render to
 1222        * @param path Context path of the application to list session information for
 1223        */
 1224       protected void sessions(PrintWriter writer, String path) {
 1225           sessions(writer, path, -1);
 1226       }
 1227   
 1228   
 1229       /**
 1230        *
 1231        * Extract the expiration request parameter
 1232        *
 1233        * @param path
 1234        * @param req
 1235        */
 1236       protected void expireSessions(PrintWriter writer, String path, HttpServletRequest req) {
 1237           int idle = -1;
 1238           String idleParam = req.getParameter("idle");
 1239           if (idleParam != null) {
 1240               try {
 1241                   idle = Integer.parseInt(idleParam);
 1242               } catch (NumberFormatException e) {
 1243                   log("Could not parse idle parameter to an int: " + idleParam);
 1244               }
 1245           }
 1246           sessions(writer, path, idle);
 1247       }
 1248   
 1249       /**
 1250        * Start the web application at the specified context path.
 1251        *
 1252        * @param writer Writer to render to
 1253        * @param path Context path of the application to be started
 1254        */
 1255       protected void start(PrintWriter writer, String path) {
 1256   
 1257           if (debug >= 1)
 1258               log("start: Starting web application at '" + path + "'");
 1259   
 1260           if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
 1261               writer.println(sm.getString("managerServlet.invalidPath",
 1262                                           RequestUtil.filter(path)));
 1263               return;
 1264           }
 1265           String displayPath = path;
 1266           if( path.equals("/") )
 1267               path = "";
 1268   
 1269           try {
 1270               Context context = (Context) host.findChild(path);
 1271               if (context == null) {
 1272                   writer.println(sm.getString("managerServlet.noContext", 
 1273                                               RequestUtil.filter(displayPath)));
 1274                   return;
 1275               }
 1276               ((Lifecycle) context).start();
 1277               if (context.getAvailable())
 1278                   writer.println
 1279                       (sm.getString("managerServlet.started", displayPath));
 1280               else
 1281                   writer.println
 1282                       (sm.getString("managerServlet.startFailed", displayPath));
 1283           } catch (Throwable t) {
 1284               getServletContext().log
 1285                   (sm.getString("managerServlet.startFailed", displayPath), t);
 1286               writer.println
 1287                   (sm.getString("managerServlet.startFailed", displayPath));
 1288               writer.println(sm.getString("managerServlet.exception",
 1289                                           t.toString()));
 1290           }
 1291   
 1292       }
 1293   
 1294   
 1295       /**
 1296        * Stop the web application at the specified context path.
 1297        *
 1298        * @param writer Writer to render to
 1299        * @param path Context path of the application to be stopped
 1300        */
 1301       protected void stop(PrintWriter writer, String path) {
 1302   
 1303           if (debug >= 1)
 1304               log("stop: Stopping web application at '" + path + "'");
 1305   
 1306           if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
 1307               writer.println(sm.getString("managerServlet.invalidPath",
 1308                                           RequestUtil.filter(path)));
 1309               return;
 1310           }
 1311           String displayPath = path;
 1312           if( path.equals("/") )
 1313               path = "";
 1314   
 1315           try {
 1316               Context context = (Context) host.findChild(path);
 1317               if (context == null) {
 1318                   writer.println(sm.getString("managerServlet.noContext", 
 1319                                               RequestUtil.filter(displayPath)));
 1320                   return;
 1321               }
 1322               // It isn't possible for the manager to stop itself
 1323               if (context.getPath().equals(this.context.getPath())) {
 1324                   writer.println(sm.getString("managerServlet.noSelf"));
 1325                   return;
 1326               }
 1327               ((Lifecycle) context).stop();
 1328               writer.println(sm.getString("managerServlet.stopped", displayPath));
 1329           } catch (Throwable t) {
 1330               log("ManagerServlet.stop[" + displayPath + "]", t);
 1331               writer.println(sm.getString("managerServlet.exception",
 1332                                           t.toString()));
 1333           }
 1334   
 1335       }
 1336   
 1337   
 1338       /**
 1339        * Undeploy the web application at the specified context path.
 1340        *
 1341        * @param writer Writer to render to
 1342        * @param path Context path of the application to be removed
 1343        */
 1344       protected void undeploy(PrintWriter writer, String path) {
 1345   
 1346           if (debug >= 1)
 1347               log("undeploy: Undeploying web application at '" + path + "'");
 1348   
 1349           if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
 1350               writer.println(sm.getString("managerServlet.invalidPath",
 1351                                           RequestUtil.filter(path)));
 1352               return;
 1353           }
 1354           String displayPath = path;
 1355           if( path.equals("/") )
 1356               path = "";
 1357   
 1358           try {
 1359   
 1360               // Validate the Context of the specified application
 1361               Context context = (Context) host.findChild(path);
 1362               if (context == null) {
 1363                   writer.println(sm.getString("managerServlet.noContext",
 1364                                               RequestUtil.filter(displayPath)));
 1365                   return;
 1366               }
 1367   
 1368               // Identify the appBase of the owning Host of this Context (if any)
 1369               String appBase = null;
 1370               File appBaseDir = null;
 1371               if (context.getParent() instanceof Host) {
 1372                   appBase = ((Host) context.getParent()).getAppBase();
 1373                   appBaseDir = new File(appBase);
 1374                   if (!appBaseDir.isAbsolute()) {
 1375                       appBaseDir = new File(System.getProperty("catalina.base"),
 1376                                             appBase);
 1377                   }
 1378               }
 1379   
 1380               if (!isDeployed(path)) {
 1381                   writer.println(sm.getString("managerServlet.notDeployed",
 1382                           RequestUtil.filter(displayPath)));
 1383                   return;
 1384               }
 1385   
 1386               if (!isServiced(path)) {
 1387                   addServiced(path);
 1388                   try {
 1389                       // Try to stop the context first to be nicer
 1390                       ((Lifecycle) context).stop();
 1391                   } catch (Throwable t) {
 1392                       // Ignore
 1393                   }
 1394                   try {
 1395                       if (path.lastIndexOf('/') > 0) {
 1396                           path = "/" + path.substring(1).replace('/','#');
 1397                       }
 1398                       File war = new File(getAppBase(), getDocBase(path) + ".war");
 1399                       File dir = new File(getAppBase(), getDocBase(path));
 1400                       File xml = new File(configBase, getConfigFile(path) + ".xml");
 1401                       if (war.exists()) {
 1402                           war.delete();
 1403                       } else if (dir.exists()) {
 1404                           undeployDir(dir);
 1405                       } else {
 1406                           xml.delete();
 1407                       }
 1408                       // Perform new deployment
 1409                       check(path.replace('#', '/'));
 1410                   } finally {
 1411                       removeServiced(path.replace('#','/'));
 1412                   }
 1413               }
 1414               writer.println(sm.getString("managerServlet.undeployed",
 1415                                           displayPath));
 1416           } catch (Throwable t) {
 1417               log("ManagerServlet.undeploy[" + displayPath + "]", t);
 1418               writer.println(sm.getString("managerServlet.exception",
 1419                                           t.toString()));
 1420           }
 1421   
 1422       }
 1423   
 1424   
 1425       // -------------------------------------------------------- Support Methods
 1426   
 1427   
 1428       /**
 1429        * Given a context path, get the config file name.
 1430        */
 1431       protected String getConfigFile(String path) {
 1432           String basename = null;
 1433           if (path.equals("")) {
 1434               basename = "ROOT";
 1435           } else {
 1436               basename = path.substring(1).replace('/', '#');
 1437           }
 1438           return (basename);
 1439       }
 1440   
 1441   
 1442       /**
 1443        * Given a context path, get the doc base.
 1444        */
 1445       protected String getDocBase(String path) {
 1446           String basename = null;
 1447           if (path.equals("")) {
 1448               basename = "ROOT";
 1449           } else {
 1450               basename = path.substring(1).replace('/', '#');
 1451           }
 1452           return (basename);
 1453       }
 1454   
 1455       
 1456       /**
 1457        * Return a File object representing the "application root" directory
 1458        * for our associated Host.
 1459        */
 1460       protected File getAppBase() {
 1461   
 1462           if (appBase != null) {
 1463               return appBase;
 1464           }
 1465   
 1466           File file = new File(host.getAppBase());
 1467           if (!file.isAbsolute())
 1468               file = new File(System.getProperty("catalina.base"),
 1469                               host.getAppBase());
 1470           try {
 1471               appBase = file.getCanonicalFile();
 1472           } catch (IOException e) {
 1473               appBase = file;
 1474           }
 1475           return (appBase);
 1476   
 1477       }
 1478   
 1479   
 1480       /**
 1481        * Invoke the isDeployed method on the deployer.
 1482        */
 1483       protected boolean isDeployed(String name) 
 1484           throws Exception {
 1485           String[] params = { name };
 1486           String[] signature = { "java.lang.String" };
 1487           Boolean result = 
 1488               (Boolean) mBeanServer.invoke(oname, "isDeployed", params, signature);
 1489           return result.booleanValue();
 1490       }
 1491       
 1492   
 1493       /**
 1494        * Invoke the check method on the deployer.
 1495        */
 1496       protected void check(String name) 
 1497           throws Exception {
 1498           String[] params = { name };
 1499           String[] signature = { "java.lang.String" };
 1500           mBeanServer.invoke(oname, "check", params, signature);
 1501       }
 1502       
 1503   
 1504       /**
 1505        * Invoke the isServiced method on the deployer.
 1506        */
 1507       protected boolean isServiced(String name) 
 1508           throws Exception {
 1509           String[] params = { name };
 1510           String[] signature = { "java.lang.String" };
 1511           Boolean result = 
 1512               (Boolean) mBeanServer.invoke(oname, "isServiced", params, signature);
 1513           return result.booleanValue();
 1514       }
 1515       
 1516   
 1517       /**
 1518        * Invoke the addServiced method on the deployer.
 1519        */
 1520       protected void addServiced(String name) 
 1521           throws Exception {
 1522           String[] params = { name };
 1523           String[] signature = { "java.lang.String" };
 1524           mBeanServer.invoke(oname, "addServiced", params, signature);
 1525       }
 1526       
 1527   
 1528       /**
 1529        * Invoke the removeServiced method on the deployer.
 1530        */
 1531       protected void removeServiced(String name) 
 1532           throws Exception {
 1533           String[] params = { name };
 1534           String[] signature = { "java.lang.String" };
 1535           mBeanServer.invoke(oname, "removeServiced", params, signature);
 1536       }
 1537       
 1538   
 1539       /**
 1540        * Delete the specified directory, including all of its contents and
 1541        * subdirectories recursively.
 1542        *
 1543        * @param dir File object representing the directory to be deleted
 1544        */
 1545       protected void undeployDir(File dir) {
 1546   
 1547           String files[] = dir.list();
 1548           if (files == null) {
 1549               files = new String[0];
 1550           }
 1551           for (int i = 0; i < files.length; i++) {
 1552               File file = new File(dir, files[i]);
 1553               if (file.isDirectory()) {
 1554                   undeployDir(file);
 1555               } else {
 1556                   file.delete();
 1557               }
 1558           }
 1559           dir.delete();
 1560   
 1561       }
 1562   
 1563   
 1564       /**
 1565        * Upload the WAR file included in this request, and store it at the
 1566        * specified file location.
 1567        *
 1568        * @param request The servlet request we are processing
 1569        * @param war The file into which we should store the uploaded WAR
 1570        *
 1571        * @exception IOException if an I/O error occurs during processing
 1572        */
 1573       protected void uploadWar(HttpServletRequest request, File war)
 1574           throws IOException {
 1575   
 1576           war.delete();
 1577           ServletInputStream istream = null;
 1578           BufferedOutputStream ostream = null;
 1579           try {
 1580               istream = request.getInputStream();
 1581               ostream =
 1582                   new BufferedOutputStream(new FileOutputStream(war), 1024);
 1583               byte buffer[] = new byte[1024];
 1584               while (true) {
 1585                   int n = istream.read(buffer);
 1586                   if (n < 0) {
 1587                       break;
 1588                   }
 1589                   ostream.write(buffer, 0, n);
 1590               }
 1591               ostream.flush();
 1592               ostream.close();
 1593               ostream = null;
 1594               istream.close();
 1595               istream = null;
 1596           } catch (IOException e) {
 1597               war.delete();
 1598               throw e;
 1599           } finally {
 1600               if (ostream != null) {
 1601                   try {
 1602                       ostream.close();
 1603                   } catch (Throwable t) {
 1604                       ;
 1605                   }
 1606                   ostream = null;
 1607               }
 1608               if (istream != null) {
 1609                   try {
 1610                       istream.close();
 1611                   } catch (Throwable t) {
 1612                       ;
 1613                   }
 1614                   istream = null;
 1615               }
 1616           }
 1617   
 1618       }
 1619   
 1620   
 1621       /**
 1622        * Copy the specified file or directory to the destination.
 1623        *
 1624        * @param src File object representing the source
 1625        * @param dest File object representing the destination
 1626        */
 1627       public static boolean copy(File src, File dest) {
 1628           boolean result = false;
 1629           try {
 1630               if( src != null &&
 1631                       !src.getCanonicalPath().equals(dest.getCanonicalPath()) ) {
 1632                   result = copyInternal(src, dest, new byte[4096]);
 1633               }
 1634           } catch (IOException e) {
 1635               e.printStackTrace();
 1636           }
 1637           return result;
 1638       }
 1639   
 1640       
 1641       /**
 1642        * Copy the specified file or directory to the destination.
 1643        *
 1644        * @param src File object representing the source
 1645        * @param dest File object representing the destination
 1646        */
 1647       public static boolean copyInternal(File src, File dest, byte[] buf) {
 1648           
 1649           boolean result = true;
 1650           
 1651           String files[] = null;
 1652           if (src.isDirectory()) {
 1653               files = src.list();
 1654               result = dest.mkdir();
 1655           } else {
 1656               files = new String[1];
 1657               files[0] = "";
 1658           }
 1659           if (files == null) {
 1660               files = new String[0];
 1661           }
 1662           for (int i = 0; (i < files.length) && result; i++) {
 1663               File fileSrc = new File(src, files[i]);
 1664               File fileDest = new File(dest, files[i]);
 1665               if (fileSrc.isDirectory()) {
 1666                   result = copyInternal(fileSrc, fileDest, buf);
 1667               } else {
 1668                   FileInputStream is = null;
 1669                   FileOutputStream os = null;
 1670                   try {
 1671                       is = new FileInputStream(fileSrc);
 1672                       os = new FileOutputStream(fileDest);
 1673                       int len = 0;
 1674                       while (true) {
 1675                           len = is.read(buf);
 1676                           if (len == -1)
 1677                               break;
 1678                           os.write(buf, 0, len);
 1679                       }
 1680                   } catch (IOException e) {
 1681                       e.printStackTrace();
 1682                       result = false;
 1683                   } finally {
 1684                       if (is != null) {
 1685                           try {
 1686                               is.close();
 1687                           } catch (IOException e) {
 1688                           }
 1689                       }
 1690                       if (os != null) {
 1691                           try {
 1692                               os.close();
 1693                           } catch (IOException e) {
 1694                           }
 1695                       }
 1696                   }
 1697               }
 1698           }
 1699           return result;
 1700           
 1701       }
 1702       
 1703       
 1704   }

Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » manager » [javadoc | source]