0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.catalina.manager;
0019:
0020: import java.io.BufferedOutputStream;
0021: import java.io.File;
0022: import java.io.FileInputStream;
0023: import java.io.FileOutputStream;
0024: import java.io.IOException;
0025: import java.io.PrintWriter;
0026: import java.util.Iterator;
0027:
0028: import javax.management.MBeanServer;
0029: import javax.management.ObjectName;
0030: import javax.naming.Binding;
0031: import javax.naming.InitialContext;
0032: import javax.naming.NamingEnumeration;
0033: import javax.naming.NamingException;
0034: import javax.servlet.ServletException;
0035: import javax.servlet.ServletInputStream;
0036: import javax.servlet.UnavailableException;
0037: import javax.servlet.http.HttpServlet;
0038: import javax.servlet.http.HttpServletRequest;
0039: import javax.servlet.http.HttpServletResponse;
0040:
0041: import org.apache.catalina.Container;
0042: import org.apache.catalina.ContainerServlet;
0043: import org.apache.catalina.Context;
0044: import org.apache.catalina.Engine;
0045: import org.apache.catalina.Globals;
0046: import org.apache.catalina.Host;
0047: import org.apache.catalina.Lifecycle;
0048: import org.apache.catalina.Role;
0049: import org.apache.catalina.Server;
0050: import org.apache.catalina.ServerFactory;
0051: import org.apache.catalina.Session;
0052: import org.apache.catalina.UserDatabase;
0053: import org.apache.catalina.Wrapper;
0054: import org.apache.catalina.core.StandardServer;
0055: import org.apache.catalina.util.RequestUtil;
0056: import org.apache.catalina.util.ServerInfo;
0057: import org.apache.catalina.util.StringManager;
0058: import org.apache.tomcat.util.modeler.Registry;
0059:
0060: /**
0061: * Servlet that enables remote management of the web applications installed
0062: * within the same virtual host as this web application is. Normally, this
0063: * functionality will be protected by a security constraint in the web
0064: * application deployment descriptor. However, this requirement can be
0065: * relaxed during testing.
0066: * <p>
0067: * This servlet examines the value returned by <code>getPathInfo()</code>
0068: * and related query parameters to determine what action is being requested.
0069: * The following actions and parameters (starting after the servlet path)
0070: * are supported:
0071: * <ul>
0072: * <li><b>/deploy?config={config-url}</b> - Install and start a new
0073: * web application, based on the contents of the context configuration
0074: * file found at the specified URL. The <code>docBase</code> attribute
0075: * of the context configuration file is used to locate the actual
0076: * WAR or directory containing the application.</li>
0077: * <li><b>/deploy?config={config-url}&war={war-url}/</b> - Install and start
0078: * a new web application, based on the contents of the context
0079: * configuration file found at <code>{config-url}</code>, overriding the
0080: * <code>docBase</code> attribute with the contents of the web
0081: * application archive found at <code>{war-url}</code>.</li>
0082: * <li><b>/deploy?path=/xxx&war={war-url}</b> - Install and start a new
0083: * web application attached to context path <code>/xxx</code>, based
0084: * on the contents of the web application archive found at the
0085: * specified URL.</li>
0086: * <li><b>/list</b> - List the context paths of all currently installed web
0087: * applications for this virtual host. Each context will be listed with
0088: * the following format <code>path:status:sessions</code>.
0089: * Where path is the context path. Status is either running or stopped.
0090: * Sessions is the number of active Sessions.</li>
0091: * <li><b>/reload?path=/xxx</b> - Reload the Java classes and resources for
0092: * the application at the specified path.</li>
0093: * <li><b>/resources?type=xxxx</b> - Enumerate the available global JNDI
0094: * resources, optionally limited to those of the specified type
0095: * (fully qualified Java class name), if available.</li>
0096: * <li><b>/roles</b> - Enumerate the available security role names and
0097: * descriptions from the user database connected to the <code>users</code>
0098: * resource reference.
0099: * <li><b>/serverinfo</b> - Display system OS and JVM properties.
0100: * <li><b>/expire?path=/xxx</b> - List session idle timeinformation about the
0101: * web application attached to context path <code>/xxx</code> for this
0102: * virtual host.</li>
0103: * <li><b>/expire?path=/xxx&idle=mm</b> - Expire sessions
0104: * for the context path <code>/xxx</code> which were idle for at
0105: * least mm minutes.</li>
0106: * <li><b>/start?path=/xxx</b> - Start the web application attached to
0107: * context path <code>/xxx</code> for this virtual host.</li>
0108: * <li><b>/stop?path=/xxx</b> - Stop the web application attached to
0109: * context path <code>/xxx</code> for this virtual host.</li>
0110: * <li><b>/undeploy?path=/xxx</b> - Shutdown and remove the web application
0111: * attached to context path <code>/xxx</code> for this virtual host,
0112: * and remove the underlying WAR file or document base directory.
0113: * (<em>NOTE</em> - This is only allowed if the WAR file or document
0114: * base is stored in the <code>appBase</code> directory of this host,
0115: * typically as a result of being placed there via the <code>/deploy</code>
0116: * command.</li>
0117: * </ul>
0118: * <p>Use <code>path=/</code> for the ROOT context.</p>
0119: * <p>The syntax of the URL for a web application archive must conform to one
0120: * of the following patterns to be successfully deployed:</p>
0121: * <ul>
0122: * <li><b>file:/absolute/path/to/a/directory</b> - You can specify the absolute
0123: * path of a directory that contains the unpacked version of a web
0124: * application. This directory will be attached to the context path you
0125: * specify without any changes.</li>
0126: * <li><b>jar:file:/absolute/path/to/a/warfile.war!/</b> - You can specify a
0127: * URL to a local web application archive file. The syntax must conform to
0128: * the rules specified by the <code>JarURLConnection</code> class for a
0129: * reference to an entire JAR file.</li>
0130: * <li><b>jar:http://hostname:port/path/to/a/warfile.war!/</b> - You can specify
0131: * a URL to a remote (HTTP-accessible) web application archive file. The
0132: * syntax must conform to the rules specified by the
0133: * <code>JarURLConnection</code> class for a reference to an entire
0134: * JAR file.</li>
0135: * </ul>
0136: * <p>
0137: * <b>NOTE</b> - Attempting to reload or remove the application containing
0138: * this servlet itself will not succeed. Therefore, this servlet should
0139: * generally be deployed as a separate web application within the virtual host
0140: * to be managed.
0141: * <p>
0142: * <b>NOTE</b> - For security reasons, this application will not operate
0143: * when accessed via the invoker servlet. You must explicitly map this servlet
0144: * with a servlet mapping, and you will always want to protect it with
0145: * appropriate security constraints as well.
0146: * <p>
0147: * The following servlet initialization parameters are recognized:
0148: * <ul>
0149: * <li><b>debug</b> - The debugging detail level that controls the amount
0150: * of information that is logged by this servlet. Default is zero.
0151: * </ul>
0152: *
0153: * @author Craig R. McClanahan
0154: * @author Remy Maucherat
0155: * @version $Revision: 532461 $ $Date: 2007-04-25 21:56:25 +0200 (mer., 25 avr. 2007) $
0156: */
0157:
0158: public class ManagerServlet extends HttpServlet implements
0159: ContainerServlet {
0160:
0161: // ----------------------------------------------------- Instance Variables
0162:
0163: /**
0164: * Path where context descriptors should be deployed.
0165: */
0166: protected File configBase = null;
0167:
0168: /**
0169: * The Context container associated with our web application.
0170: */
0171: protected Context context = null;
0172:
0173: /**
0174: * The debugging detail level for this servlet.
0175: */
0176: protected int debug = 1;
0177:
0178: /**
0179: * File object representing the directory into which the deploy() command
0180: * will store the WAR and context configuration files that have been
0181: * uploaded.
0182: */
0183: protected File deployed = null;
0184:
0185: /**
0186: * Path used to store revisions of webapps.
0187: */
0188: protected File versioned = null;
0189:
0190: /**
0191: * Path used to store context descriptors.
0192: */
0193: protected File contextDescriptors = null;
0194:
0195: /**
0196: * The associated host.
0197: */
0198: protected Host host = null;
0199:
0200: /**
0201: * The host appBase.
0202: */
0203: protected File appBase = null;
0204:
0205: /**
0206: * MBean server.
0207: */
0208: protected MBeanServer mBeanServer = null;
0209:
0210: /**
0211: * The associated deployer ObjectName.
0212: */
0213: protected ObjectName oname = null;
0214:
0215: /**
0216: * The global JNDI <code>NamingContext</code> for this server,
0217: * if available.
0218: */
0219: protected javax.naming.Context global = null;
0220:
0221: /**
0222: * The string manager for this package.
0223: */
0224: protected static StringManager sm = StringManager
0225: .getManager(Constants.Package);
0226:
0227: /**
0228: * The Wrapper container associated with this servlet.
0229: */
0230: protected Wrapper wrapper = null;
0231:
0232: // ----------------------------------------------- ContainerServlet Methods
0233:
0234: /**
0235: * Return the Wrapper with which we are associated.
0236: */
0237: public Wrapper getWrapper() {
0238:
0239: return (this .wrapper);
0240:
0241: }
0242:
0243: /**
0244: * Set the Wrapper with which we are associated.
0245: *
0246: * @param wrapper The new wrapper
0247: */
0248: public void setWrapper(Wrapper wrapper) {
0249:
0250: this .wrapper = wrapper;
0251: if (wrapper == null) {
0252: context = null;
0253: host = null;
0254: oname = null;
0255: } else {
0256: context = (Context) wrapper.getParent();
0257: host = (Host) context.getParent();
0258: Engine engine = (Engine) host.getParent();
0259: try {
0260: oname = new ObjectName(engine.getName()
0261: + ":type=Deployer,host=" + host.getName());
0262: } catch (Exception e) {
0263: // ?
0264: }
0265: }
0266:
0267: // Retrieve the MBean server
0268: mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
0269:
0270: }
0271:
0272: // --------------------------------------------------------- Public Methods
0273:
0274: /**
0275: * Finalize this servlet.
0276: */
0277: public void destroy() {
0278:
0279: ; // No actions necessary
0280:
0281: }
0282:
0283: /**
0284: * Process a GET request for the specified resource.
0285: *
0286: * @param request The servlet request we are processing
0287: * @param response The servlet response we are creating
0288: *
0289: * @exception IOException if an input/output error occurs
0290: * @exception ServletException if a servlet-specified error occurs
0291: */
0292: public void doGet(HttpServletRequest request,
0293: HttpServletResponse response) throws IOException,
0294: ServletException {
0295:
0296: // Verify that we were not accessed using the invoker servlet
0297: if (request.getAttribute(Globals.INVOKED_ATTR) != null)
0298: throw new UnavailableException(sm
0299: .getString("managerServlet.cannotInvoke"));
0300:
0301: // Identify the request parameters that we need
0302: String command = request.getPathInfo();
0303: if (command == null)
0304: command = request.getServletPath();
0305: String config = request.getParameter("config");
0306: String path = request.getParameter("path");
0307: String type = request.getParameter("type");
0308: String war = request.getParameter("war");
0309: String tag = request.getParameter("tag");
0310: boolean update = false;
0311: if ((request.getParameter("update") != null)
0312: && (request.getParameter("update").equals("true"))) {
0313: update = true;
0314: }
0315:
0316: // Prepare our output writer to generate the response message
0317: response.setContentType("text/plain; charset="
0318: + Constants.CHARSET);
0319: PrintWriter writer = response.getWriter();
0320:
0321: // Process the requested command (note - "/deploy" is not listed here)
0322: if (command == null) {
0323: writer.println(sm.getString("managerServlet.noCommand"));
0324: } else if (command.equals("/deploy")) {
0325: if (war != null || config != null) {
0326: deploy(writer, config, path, war, update);
0327: } else {
0328: deploy(writer, path, tag);
0329: }
0330: } else if (command.equals("/install")) {
0331: // Deprecated
0332: deploy(writer, config, path, war, false);
0333: } else if (command.equals("/list")) {
0334: list(writer);
0335: } else if (command.equals("/reload")) {
0336: reload(writer, path);
0337: } else if (command.equals("/remove")) {
0338: // Deprecated
0339: undeploy(writer, path);
0340: } else if (command.equals("/resources")) {
0341: resources(writer, type);
0342: } else if (command.equals("/roles")) {
0343: roles(writer);
0344: } else if (command.equals("/save")) {
0345: save(writer, path);
0346: } else if (command.equals("/serverinfo")) {
0347: serverinfo(writer);
0348: } else if (command.equals("/expire")) {
0349: expireSessions(writer, path, request);
0350: } else if (command.equals("/start")) {
0351: start(writer, path);
0352: } else if (command.equals("/stop")) {
0353: stop(writer, path);
0354: } else if (command.equals("/undeploy")) {
0355: undeploy(writer, path);
0356: } else {
0357: writer.println(sm.getString(
0358: "managerServlet.unknownCommand", command));
0359: }
0360:
0361: // Finish up the response
0362: writer.flush();
0363: writer.close();
0364:
0365: }
0366:
0367: /**
0368: * Process a PUT request for the specified resource.
0369: *
0370: * @param request The servlet request we are processing
0371: * @param response The servlet response we are creating
0372: *
0373: * @exception IOException if an input/output error occurs
0374: * @exception ServletException if a servlet-specified error occurs
0375: */
0376: public void doPut(HttpServletRequest request,
0377: HttpServletResponse response) throws IOException,
0378: ServletException {
0379:
0380: // Verify that we were not accessed using the invoker servlet
0381: if (request.getAttribute(Globals.INVOKED_ATTR) != null)
0382: throw new UnavailableException(sm
0383: .getString("managerServlet.cannotInvoke"));
0384:
0385: // Identify the request parameters that we need
0386: String command = request.getPathInfo();
0387: if (command == null)
0388: command = request.getServletPath();
0389: String path = request.getParameter("path");
0390: String tag = request.getParameter("tag");
0391: boolean update = false;
0392: if ((request.getParameter("update") != null)
0393: && (request.getParameter("update").equals("true"))) {
0394: update = true;
0395: }
0396:
0397: // Prepare our output writer to generate the response message
0398: response.setContentType("text/plain;charset="
0399: + Constants.CHARSET);
0400: PrintWriter writer = response.getWriter();
0401:
0402: // Process the requested command
0403: if (command == null) {
0404: writer.println(sm.getString("managerServlet.noCommand"));
0405: } else if (command.equals("/deploy")) {
0406: deploy(writer, path, tag, update, request);
0407: } else {
0408: writer.println(sm.getString(
0409: "managerServlet.unknownCommand", command));
0410: }
0411:
0412: // Finish up the response
0413: writer.flush();
0414: writer.close();
0415:
0416: }
0417:
0418: /**
0419: * Initialize this servlet.
0420: */
0421: public void init() throws ServletException {
0422:
0423: // Ensure that our ContainerServlet properties have been set
0424: if ((wrapper == null) || (context == null))
0425: throw new UnavailableException(sm
0426: .getString("managerServlet.noWrapper"));
0427:
0428: // Verify that we were not accessed using the invoker servlet
0429: String servletName = getServletConfig().getServletName();
0430: if (servletName == null)
0431: servletName = "";
0432: if (servletName.startsWith("org.apache.catalina.INVOKER."))
0433: throw new UnavailableException(sm
0434: .getString("managerServlet.cannotInvoke"));
0435:
0436: // Set our properties from the initialization parameters
0437: String value = null;
0438: try {
0439: value = getServletConfig().getInitParameter("debug");
0440: debug = Integer.parseInt(value);
0441: } catch (Throwable t) {
0442: ;
0443: }
0444:
0445: // Acquire global JNDI resources if available
0446: Server server = ServerFactory.getServer();
0447: if ((server != null) && (server instanceof StandardServer)) {
0448: global = ((StandardServer) server).getGlobalNamingContext();
0449: }
0450:
0451: // Calculate the directory into which we will be deploying applications
0452: versioned = (File) getServletContext().getAttribute(
0453: "javax.servlet.context.tempdir");
0454:
0455: // Identify the appBase of the owning Host of this Context
0456: // (if any)
0457: String appBase = ((Host) context.getParent()).getAppBase();
0458: deployed = new File(appBase);
0459: if (!deployed.isAbsolute()) {
0460: deployed = new File(System.getProperty("catalina.base"),
0461: appBase);
0462: }
0463: configBase = new File(System.getProperty("catalina.base"),
0464: "conf");
0465: Container container = context;
0466: Container host = null;
0467: Container engine = null;
0468: while (container != null) {
0469: if (container instanceof Host)
0470: host = container;
0471: if (container instanceof Engine)
0472: engine = container;
0473: container = container.getParent();
0474: }
0475: if (engine != null) {
0476: configBase = new File(configBase, engine.getName());
0477: }
0478: if (host != null) {
0479: configBase = new File(configBase, host.getName());
0480: }
0481: // Note: The directory must exist for this to work.
0482:
0483: // Log debugging messages as necessary
0484: if (debug >= 1) {
0485: log("init: Associated with Deployer '" + oname + "'");
0486: if (global != null) {
0487: log("init: Global resources are available");
0488: }
0489: }
0490:
0491: }
0492:
0493: // -------------------------------------------------------- Private Methods
0494:
0495: /**
0496: * Store server configuration.
0497: *
0498: * @param path Optional context path to save
0499: */
0500: protected synchronized void save(PrintWriter writer, String path) {
0501:
0502: Server server = ServerFactory.getServer();
0503:
0504: if (!(server instanceof StandardServer)) {
0505: writer.println(sm.getString("managerServlet.saveFail",
0506: server));
0507: return;
0508: }
0509:
0510: if ((path == null) || path.length() == 0
0511: || !path.startsWith("/")) {
0512: try {
0513: ((StandardServer) server).storeConfig();
0514: writer.println(sm.getString("managerServlet.saved"));
0515: } catch (Exception e) {
0516: log("managerServlet.storeConfig", e);
0517: writer.println(sm.getString("managerServlet.exception",
0518: e.toString()));
0519: return;
0520: }
0521: } else {
0522: String contextPath = path;
0523: if (path.equals("/")) {
0524: contextPath = "";
0525: }
0526: Context context = (Context) host.findChild(contextPath);
0527: if (context == null) {
0528: writer.println(sm.getString("managerServlet.noContext",
0529: path));
0530: return;
0531: }
0532: try {
0533: ((StandardServer) server).storeContext(context);
0534: writer.println(sm.getString(
0535: "managerServlet.savedContext", path));
0536: } catch (Exception e) {
0537: log("managerServlet.save[" + path + "]", e);
0538: writer.println(sm.getString("managerServlet.exception",
0539: e.toString()));
0540: return;
0541: }
0542: }
0543:
0544: }
0545:
0546: /**
0547: * Deploy a web application archive (included in the current request)
0548: * at the specified context path.
0549: *
0550: * @param writer Writer to render results to
0551: * @param path Context path of the application to be installed
0552: * @param tag Tag to be associated with the webapp
0553: * @param request Servlet request we are processing
0554: */
0555: protected synchronized void deploy(PrintWriter writer, String path,
0556: String tag, boolean update, HttpServletRequest request) {
0557:
0558: if (debug >= 1) {
0559: log("deploy: Deploying web application at '" + path + "'");
0560: }
0561:
0562: // Validate the requested context path
0563: if ((path == null) || path.length() == 0
0564: || !path.startsWith("/")) {
0565: writer.println(sm.getString("managerServlet.invalidPath",
0566: path));
0567: return;
0568: }
0569: String displayPath = path;
0570: if (path.equals("/"))
0571: path = "";
0572: String basename = getDocBase(path);
0573:
0574: // Check if app already exists, or undeploy it if updating
0575: Context context = (Context) host.findChild(path);
0576: if (update) {
0577: if (context != null) {
0578: undeploy(writer, displayPath);
0579: }
0580: context = (Context) host.findChild(path);
0581: }
0582: if (context != null) {
0583: writer.println(sm.getString(
0584: "managerServlet.alreadyContext", displayPath));
0585: return;
0586: }
0587:
0588: // Calculate the base path
0589: File deployedPath = deployed;
0590: if (tag != null) {
0591: deployedPath = new File(versioned, tag);
0592: deployedPath.mkdirs();
0593: }
0594:
0595: // Upload the web application archive to a local WAR file
0596: File localWar = new File(deployedPath, basename + ".war");
0597: if (debug >= 2) {
0598: log("Uploading WAR file to " + localWar);
0599: }
0600:
0601: // Copy WAR to appBase
0602: try {
0603: if (!isServiced(path)) {
0604: addServiced(path);
0605: try {
0606: // Upload WAR
0607: uploadWar(request, localWar);
0608: // Copy WAR and XML to the host app base if needed
0609: if (tag != null) {
0610: deployedPath = deployed;
0611: File localWarCopy = new File(deployedPath,
0612: basename + ".war");
0613: copy(localWar, localWarCopy);
0614: localWar = localWarCopy;
0615: copy(localWar, new File(getAppBase(), basename
0616: + ".war"));
0617: }
0618: // Perform new deployment
0619: check(path);
0620: } finally {
0621: removeServiced(path);
0622: }
0623: }
0624: } catch (Exception e) {
0625: log("managerServlet.check[" + displayPath + "]", e);
0626: writer.println(sm.getString("managerServlet.exception", e
0627: .toString()));
0628: return;
0629: }
0630:
0631: context = (Context) host.findChild(path);
0632: if (context != null && context.getConfigured()) {
0633: writer.println(sm.getString("managerServlet.deployed",
0634: displayPath));
0635: } else {
0636: // Something failed
0637: writer.println(sm.getString("managerServlet.deployFailed",
0638: displayPath));
0639: }
0640:
0641: }
0642:
0643: /**
0644: * Install an application for the specified path from the specified
0645: * web application archive.
0646: *
0647: * @param writer Writer to render results to
0648: * @param tag Revision tag to deploy from
0649: * @param path Context path of the application to be installed
0650: */
0651: protected void deploy(PrintWriter writer, String path, String tag) {
0652:
0653: // Validate the requested context path
0654: if ((path == null) || path.length() == 0
0655: || !path.startsWith("/")) {
0656: writer.println(sm.getString("managerServlet.invalidPath",
0657: path));
0658: return;
0659: }
0660: String displayPath = path;
0661: if (path.equals("/"))
0662: path = "";
0663:
0664: // Calculate the base path
0665: File deployedPath = versioned;
0666: if (tag != null) {
0667: deployedPath = new File(deployedPath, tag);
0668: }
0669:
0670: // Find the local WAR file
0671: File localWar = new File(deployedPath, getDocBase(path)
0672: + ".war");
0673: // Find the local context deployment file (if any)
0674: File localXml = new File(configBase, getConfigFile(path)
0675: + ".xml");
0676:
0677: // Check if app already exists, or undeploy it if updating
0678: Context context = (Context) host.findChild(path);
0679: if (context != null) {
0680: undeploy(writer, displayPath);
0681: }
0682:
0683: // Copy WAR to appBase
0684: try {
0685: if (!isServiced(path)) {
0686: addServiced(path);
0687: try {
0688: copy(localWar, new File(getAppBase(),
0689: getDocBase(path) + ".war"));
0690: // Perform new deployment
0691: check(path);
0692: } finally {
0693: removeServiced(path);
0694: }
0695: }
0696: } catch (Exception e) {
0697: log("managerServlet.check[" + displayPath + "]", e);
0698: writer.println(sm.getString("managerServlet.exception", e
0699: .toString()));
0700: return;
0701: }
0702:
0703: context = (Context) host.findChild(path);
0704: if (context != null && context.getConfigured()) {
0705: writer.println(sm.getString("managerServlet.deployed",
0706: displayPath));
0707: } else {
0708: // Something failed
0709: writer.println(sm.getString("managerServlet.deployFailed",
0710: displayPath));
0711: }
0712:
0713: }
0714:
0715: /**
0716: * Install an application for the specified path from the specified
0717: * web application archive.
0718: *
0719: * @param writer Writer to render results to
0720: * @param config URL of the context configuration file to be installed
0721: * @param path Context path of the application to be installed
0722: * @param war URL of the web application archive to be installed
0723: * @param update true to override any existing webapp on the path
0724: */
0725: protected void deploy(PrintWriter writer, String config,
0726: String path, String war, boolean update) {
0727:
0728: if (config != null && config.length() == 0) {
0729: config = null;
0730: }
0731: if (war != null && war.length() == 0) {
0732: war = null;
0733: }
0734:
0735: if (debug >= 1) {
0736: if (config != null && config.length() > 0) {
0737: if (war != null) {
0738: log("install: Installing context configuration at '"
0739: + config + "' from '" + war + "'");
0740: } else {
0741: log("install: Installing context configuration at '"
0742: + config + "'");
0743: }
0744: } else {
0745: if (path != null && path.length() > 0) {
0746: log("install: Installing web application at '"
0747: + path + "' from '" + war + "'");
0748: } else {
0749: log("install: Installing web application from '"
0750: + war + "'");
0751: }
0752: }
0753: }
0754:
0755: if (path == null || path.length() == 0 || !path.startsWith("/")) {
0756: writer.println(sm.getString("managerServlet.invalidPath",
0757: RequestUtil.filter(path)));
0758: return;
0759: }
0760: String displayPath = path;
0761: if ("/".equals(path)) {
0762: path = "";
0763: }
0764:
0765: // Check if app already exists, or undeploy it if updating
0766: Context context = (Context) host.findChild(path);
0767: if (update) {
0768: if (context != null) {
0769: undeploy(writer, displayPath);
0770: }
0771: context = (Context) host.findChild(path);
0772: }
0773: if (context != null) {
0774: writer.println(sm.getString(
0775: "managerServlet.alreadyContext", displayPath));
0776: return;
0777: }
0778:
0779: if (config != null && (config.startsWith("file:"))) {
0780: config = config.substring("file:".length());
0781: }
0782: if (war != null && (war.startsWith("file:"))) {
0783: war = war.substring("file:".length());
0784: }
0785:
0786: try {
0787: if (!isServiced(path)) {
0788: addServiced(path);
0789: try {
0790: if (config != null) {
0791: configBase.mkdirs();
0792: copy(new File(config), new File(configBase,
0793: getConfigFile(path) + ".xml"));
0794: }
0795: if (war != null) {
0796: if (war.endsWith(".war")) {
0797: copy(new File(war), new File(getAppBase(),
0798: getDocBase(path) + ".war"));
0799: } else {
0800: copy(new File(war), new File(getAppBase(),
0801: getDocBase(path)));
0802: }
0803: }
0804: // Perform new deployment
0805: check(path);
0806: } finally {
0807: removeServiced(path);
0808: }
0809: }
0810: context = (Context) host.findChild(path);
0811: if (context != null && context.getConfigured()) {
0812: writer.println(sm.getString("managerServlet.deployed",
0813: displayPath));
0814: } else {
0815: // Something failed
0816: writer.println(sm.getString(
0817: "managerServlet.deployFailed", displayPath));
0818: }
0819: } catch (Throwable t) {
0820: log("ManagerServlet.install[" + displayPath + "]", t);
0821: writer.println(sm.getString("managerServlet.exception", t
0822: .toString()));
0823: }
0824:
0825: }
0826:
0827: /**
0828: * Render a list of the currently active Contexts in our virtual host.
0829: *
0830: * @param writer Writer to render to
0831: */
0832: protected void list(PrintWriter writer) {
0833:
0834: if (debug >= 1)
0835: log("list: Listing contexts for virtual host '"
0836: + host.getName() + "'");
0837:
0838: writer.println(sm.getString("managerServlet.listed", host
0839: .getName()));
0840: Container[] contexts = host.findChildren();
0841: for (int i = 0; i < contexts.length; i++) {
0842: Context context = (Context) contexts[i];
0843: String displayPath = context.getPath();
0844: if (displayPath.equals(""))
0845: displayPath = "/";
0846: if (context != null) {
0847: if (context.getAvailable()) {
0848: writer.println(sm.getString(
0849: "managerServlet.listitem", displayPath,
0850: "running", ""
0851: + context.getManager()
0852: .findSessions().length,
0853: context.getDocBase()));
0854: } else {
0855: writer.println(sm.getString(
0856: "managerServlet.listitem", displayPath,
0857: "stopped", "0", context.getDocBase()));
0858: }
0859: }
0860: }
0861: }
0862:
0863: /**
0864: * Reload the web application at the specified context path.
0865: *
0866: * @param writer Writer to render to
0867: * @param path Context path of the application to be restarted
0868: */
0869: protected void reload(PrintWriter writer, String path) {
0870:
0871: if (debug >= 1)
0872: log("restart: Reloading web application at '" + path + "'");
0873:
0874: if ((path == null)
0875: || (!path.startsWith("/") && path.equals(""))) {
0876: writer.println(sm.getString("managerServlet.invalidPath",
0877: RequestUtil.filter(path)));
0878: return;
0879: }
0880: String displayPath = path;
0881: if (path.equals("/"))
0882: path = "";
0883:
0884: try {
0885: Context context = (Context) host.findChild(path);
0886: if (context == null) {
0887: writer.println(sm.getString("managerServlet.noContext",
0888: RequestUtil.filter(displayPath)));
0889: return;
0890: }
0891: // It isn't possible for the manager to reload itself
0892: if (context.getPath().equals(this .context.getPath())) {
0893: writer.println(sm.getString("managerServlet.noSelf"));
0894: return;
0895: }
0896: context.reload();
0897: writer.println(sm.getString("managerServlet.reloaded",
0898: displayPath));
0899: } catch (Throwable t) {
0900: log("ManagerServlet.reload[" + displayPath + "]", t);
0901: writer.println(sm.getString("managerServlet.exception", t
0902: .toString()));
0903: }
0904:
0905: }
0906:
0907: /**
0908: * Render a list of available global JNDI resources.
0909: *
0910: * @param type Fully qualified class name of the resource type of interest,
0911: * or <code>null</code> to list resources of all types
0912: */
0913: protected void resources(PrintWriter writer, String type) {
0914:
0915: if (debug >= 1) {
0916: if (type != null) {
0917: log("resources: Listing resources of type " + type);
0918: } else {
0919: log("resources: Listing resources of all types");
0920: }
0921: }
0922:
0923: // Is the global JNDI resources context available?
0924: if (global == null) {
0925: writer.println(sm.getString("managerServlet.noGlobal"));
0926: return;
0927: }
0928:
0929: // Enumerate the global JNDI resources of the requested type
0930: if (type != null) {
0931: writer.println(sm.getString("managerServlet.resourcesType",
0932: type));
0933: } else {
0934: writer.println(sm.getString("managerServlet.resourcesAll"));
0935: }
0936:
0937: Class clazz = null;
0938: try {
0939: if (type != null) {
0940: clazz = Class.forName(type);
0941: }
0942: } catch (Throwable t) {
0943: log("ManagerServlet.resources[" + type + "]", t);
0944: writer.println(sm.getString("managerServlet.exception", t
0945: .toString()));
0946: return;
0947: }
0948:
0949: printResources(writer, "", global, type, clazz);
0950:
0951: }
0952:
0953: /**
0954: * List the resources of the given context.
0955: */
0956: protected void printResources(PrintWriter writer, String prefix,
0957: javax.naming.Context namingContext, String type, Class clazz) {
0958:
0959: try {
0960: NamingEnumeration items = namingContext.listBindings("");
0961: while (items.hasMore()) {
0962: Binding item = (Binding) items.next();
0963: if (item.getObject() instanceof javax.naming.Context) {
0964: printResources(writer, prefix + item.getName()
0965: + "/", (javax.naming.Context) item
0966: .getObject(), type, clazz);
0967: } else {
0968: if ((clazz != null)
0969: && (!(clazz.isInstance(item.getObject())))) {
0970: continue;
0971: }
0972: writer.print(prefix + item.getName());
0973: writer.print(':');
0974: writer.print(item.getClassName());
0975: // Do we want a description if available?
0976: writer.println();
0977: }
0978: }
0979: } catch (Throwable t) {
0980: log("ManagerServlet.resources[" + type + "]", t);
0981: writer.println(sm.getString("managerServlet.exception", t
0982: .toString()));
0983: }
0984:
0985: }
0986:
0987: /**
0988: * Render a list of security role names (and corresponding descriptions)
0989: * from the <code>org.apache.catalina.UserDatabase</code> resource that is
0990: * connected to the <code>users</code> resource reference. Typically, this
0991: * will be the global user database, but can be adjusted if you have
0992: * different user databases for different virtual hosts.
0993: *
0994: * @param writer Writer to render to
0995: */
0996: protected void roles(PrintWriter writer) {
0997:
0998: if (debug >= 1) {
0999: log("roles: List security roles from user database");
1000: }
1001:
1002: // Look up the UserDatabase instance we should use
1003: UserDatabase database = null;
1004: try {
1005: InitialContext ic = new InitialContext();
1006: database = (UserDatabase) ic.lookup("java:comp/env/users");
1007: } catch (NamingException e) {
1008: writer.println(sm
1009: .getString("managerServlet.userDatabaseError"));
1010: log("java:comp/env/users", e);
1011: return;
1012: }
1013: if (database == null) {
1014: writer.println(sm
1015: .getString("managerServlet.userDatabaseMissing"));
1016: return;
1017: }
1018:
1019: // Enumerate the available roles
1020: writer.println(sm.getString("managerServlet.rolesList"));
1021: Iterator roles = database.getRoles();
1022: if (roles != null) {
1023: while (roles.hasNext()) {
1024: Role role = (Role) roles.next();
1025: writer.print(role.getRolename());
1026: writer.print(':');
1027: if (role.getDescription() != null) {
1028: writer.print(role.getDescription());
1029: }
1030: writer.println();
1031: }
1032: }
1033:
1034: }
1035:
1036: /**
1037: * Writes System OS and JVM properties.
1038: * @param writer Writer to render to
1039: */
1040: protected void serverinfo(PrintWriter writer) {
1041: if (debug >= 1)
1042: log("serverinfo");
1043: try {
1044: StringBuffer props = new StringBuffer();
1045: props.append("OK - Server info");
1046: props.append("\nTomcat Version: ");
1047: props.append(ServerInfo.getServerInfo());
1048: props.append("\nOS Name: ");
1049: props.append(System.getProperty("os.name"));
1050: props.append("\nOS Version: ");
1051: props.append(System.getProperty("os.version"));
1052: props.append("\nOS Architecture: ");
1053: props.append(System.getProperty("os.arch"));
1054: props.append("\nJVM Version: ");
1055: props.append(System.getProperty("java.runtime.version"));
1056: props.append("\nJVM Vendor: ");
1057: props.append(System.getProperty("java.vm.vendor"));
1058: writer.println(props.toString());
1059: } catch (Throwable t) {
1060: getServletContext().log("ManagerServlet.serverinfo", t);
1061: writer.println(sm.getString("managerServlet.exception", t
1062: .toString()));
1063: }
1064: }
1065:
1066: /**
1067: * Session information for the web application at the specified context path.
1068: * Displays a profile of session lastAccessedTime listing number
1069: * of sessions for each 10 minute interval up to 10 hours.
1070: *
1071: * @param writer Writer to render to
1072: * @param path Context path of the application to list session information for
1073: * @param idle Expire all sessions with idle time ≥ idle for this context
1074: */
1075: protected void sessions(PrintWriter writer, String path, int idle) {
1076:
1077: if (debug >= 1) {
1078: log("sessions: Session information for web application at '"
1079: + path + "'");
1080: if (idle >= 0)
1081: log("sessions: Session expiration for " + idle
1082: + " minutes '" + path + "'");
1083: }
1084:
1085: if ((path == null)
1086: || (!path.startsWith("/") && path.equals(""))) {
1087: writer.println(sm.getString("managerServlet.invalidPath",
1088: RequestUtil.filter(path)));
1089: return;
1090: }
1091: String displayPath = path;
1092: if (path.equals("/"))
1093: path = "";
1094: try {
1095: Context context = (Context) host.findChild(path);
1096: if (context == null) {
1097: writer.println(sm.getString("managerServlet.noContext",
1098: RequestUtil.filter(displayPath)));
1099: return;
1100: }
1101: int maxCount = 60;
1102: int maxInactiveInterval = context.getManager()
1103: .getMaxInactiveInterval() / 60;
1104: int histoInterval = maxInactiveInterval / maxCount;
1105: if (histoInterval * maxCount < maxInactiveInterval)
1106: histoInterval++;
1107: maxCount = maxInactiveInterval / histoInterval;
1108: if (histoInterval * maxCount < maxInactiveInterval)
1109: maxCount++;
1110:
1111: writer.println(sm.getString("managerServlet.sessions",
1112: displayPath));
1113: writer.println(sm.getString(
1114: "managerServlet.sessiondefaultmax", ""
1115: + maxInactiveInterval));
1116: Session[] sessions = context.getManager().findSessions();
1117: int[] timeout = new int[maxCount];
1118: int notimeout = 0;
1119: int expired = 0;
1120: long now = System.currentTimeMillis();
1121: for (int i = 0; i < sessions.length; i++) {
1122: int time = (int) ((now - sessions[i]
1123: .getLastAccessedTime()) / 1000);
1124: if (idle >= 0 && time >= idle * 60) {
1125: sessions[i].expire();
1126: idle++;
1127: }
1128: time = time / 60 / histoInterval;
1129: if (time < 0)
1130: notimeout++;
1131: else if (time >= maxCount)
1132: timeout[maxCount - 1]++;
1133: else
1134: timeout[time]++;
1135: }
1136: if (timeout[0] > 0)
1137: writer.println(sm.getString(
1138: "managerServlet.sessiontimeout", "<"
1139: + histoInterval, "" + timeout[0]));
1140: for (int i = 1; i < maxCount - 1; i++) {
1141: if (timeout[i] > 0)
1142: writer.println(sm.getString(
1143: "managerServlet.sessiontimeout", "" + (i)
1144: * histoInterval + " - <" + (i + 1)
1145: * histoInterval, "" + timeout[i]));
1146: }
1147: if (timeout[maxCount - 1] > 0)
1148: writer.println(sm.getString(
1149: "managerServlet.sessiontimeout", ">="
1150: + maxCount * histoInterval, ""
1151: + timeout[maxCount - 1]));
1152: if (notimeout > 0)
1153: writer.println(sm.getString(
1154: "managerServlet.sessiontimeout", "unlimited",
1155: "" + notimeout));
1156: if (idle >= 0)
1157: writer.println(sm.getString(
1158: "managerServlet.sessiontimeout", "" + idle,
1159: "expired " + expired));
1160: } catch (Throwable t) {
1161: log("ManagerServlet.sessions[" + displayPath + "]", t);
1162: writer.println(sm.getString("managerServlet.exception", t
1163: .toString()));
1164: }
1165:
1166: }
1167:
1168: /**
1169: * Session information for the web application at the specified context path.
1170: * Displays a profile of session lastAccessedTime listing number
1171: * of sessions for each 10 minute interval up to 10 hours.
1172: *
1173: * @param writer Writer to render to
1174: * @param path Context path of the application to list session information for
1175: */
1176: protected void sessions(PrintWriter writer, String path) {
1177: sessions(writer, path, -1);
1178: }
1179:
1180: /**
1181: *
1182: * Extract the expiration request parameter
1183: *
1184: * @param path
1185: * @param req
1186: */
1187: protected void expireSessions(PrintWriter writer, String path,
1188: HttpServletRequest req) {
1189: int idle = -1;
1190: String idleParam = req.getParameter("idle");
1191: if (idleParam != null) {
1192: try {
1193: idle = Integer.parseInt(idleParam);
1194: } catch (NumberFormatException e) {
1195: log("Could not parse idle parameter to an int: "
1196: + idleParam);
1197: }
1198: }
1199: sessions(writer, path, idle);
1200: }
1201:
1202: /**
1203: * Start the web application at the specified context path.
1204: *
1205: * @param writer Writer to render to
1206: * @param path Context path of the application to be started
1207: */
1208: protected void start(PrintWriter writer, String path) {
1209:
1210: if (debug >= 1)
1211: log("start: Starting web application at '" + path + "'");
1212:
1213: if ((path == null)
1214: || (!path.startsWith("/") && path.equals(""))) {
1215: writer.println(sm.getString("managerServlet.invalidPath",
1216: RequestUtil.filter(path)));
1217: return;
1218: }
1219: String displayPath = path;
1220: if (path.equals("/"))
1221: path = "";
1222:
1223: try {
1224: Context context = (Context) host.findChild(path);
1225: if (context == null) {
1226: writer.println(sm.getString("managerServlet.noContext",
1227: RequestUtil.filter(displayPath)));
1228: return;
1229: }
1230: ((Lifecycle) context).start();
1231: if (context.getAvailable())
1232: writer.println(sm.getString("managerServlet.started",
1233: displayPath));
1234: else
1235: writer.println(sm.getString(
1236: "managerServlet.startFailed", displayPath));
1237: } catch (Throwable t) {
1238: getServletContext().log(
1239: sm.getString("managerServlet.startFailed",
1240: displayPath), t);
1241: writer.println(sm.getString("managerServlet.startFailed",
1242: displayPath));
1243: writer.println(sm.getString("managerServlet.exception", t
1244: .toString()));
1245: }
1246:
1247: }
1248:
1249: /**
1250: * Stop 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 stopped
1254: */
1255: protected void stop(PrintWriter writer, String path) {
1256:
1257: if (debug >= 1)
1258: log("stop: Stopping web application at '" + path + "'");
1259:
1260: if ((path == null)
1261: || (!path.startsWith("/") && path.equals(""))) {
1262: writer.println(sm.getString("managerServlet.invalidPath",
1263: RequestUtil.filter(path)));
1264: return;
1265: }
1266: String displayPath = path;
1267: if (path.equals("/"))
1268: path = "";
1269:
1270: try {
1271: Context context = (Context) host.findChild(path);
1272: if (context == null) {
1273: writer.println(sm.getString("managerServlet.noContext",
1274: RequestUtil.filter(displayPath)));
1275: return;
1276: }
1277: // It isn't possible for the manager to stop itself
1278: if (context.getPath().equals(this .context.getPath())) {
1279: writer.println(sm.getString("managerServlet.noSelf"));
1280: return;
1281: }
1282: ((Lifecycle) context).stop();
1283: writer.println(sm.getString("managerServlet.stopped",
1284: displayPath));
1285: } catch (Throwable t) {
1286: log("ManagerServlet.stop[" + displayPath + "]", t);
1287: writer.println(sm.getString("managerServlet.exception", t
1288: .toString()));
1289: }
1290:
1291: }
1292:
1293: /**
1294: * Undeploy the web application at the specified context path.
1295: *
1296: * @param writer Writer to render to
1297: * @param path Context path of the application to be removed
1298: */
1299: protected void undeploy(PrintWriter writer, String path) {
1300:
1301: if (debug >= 1)
1302: log("undeploy: Undeploying web application at '" + path
1303: + "'");
1304:
1305: if ((path == null)
1306: || (!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:
1317: // Validate the Context of the specified application
1318: Context context = (Context) host.findChild(path);
1319: if (context == null) {
1320: writer.println(sm.getString("managerServlet.noContext",
1321: RequestUtil.filter(displayPath)));
1322: return;
1323: }
1324:
1325: // Identify the appBase of the owning Host of this Context (if any)
1326: String appBase = null;
1327: File appBaseDir = null;
1328: if (context.getParent() instanceof Host) {
1329: appBase = ((Host) context.getParent()).getAppBase();
1330: appBaseDir = new File(appBase);
1331: if (!appBaseDir.isAbsolute()) {
1332: appBaseDir = new File(System
1333: .getProperty("catalina.base"), appBase);
1334: }
1335: }
1336:
1337: if (!isDeployed(path)) {
1338: writer.println(sm.getString(
1339: "managerServlet.notDeployed", RequestUtil
1340: .filter(displayPath)));
1341: return;
1342: }
1343:
1344: if (!isServiced(path)) {
1345: addServiced(path);
1346: try {
1347: // Try to stop the context first to be nicer
1348: ((Lifecycle) context).stop();
1349: } catch (Throwable t) {
1350: // Ignore
1351: }
1352: try {
1353: File war = new File(getAppBase(), getDocBase(path)
1354: + ".war");
1355: File dir = new File(getAppBase(), getDocBase(path));
1356: File xml = new File(configBase, getConfigFile(path)
1357: + ".xml");
1358: if (war.exists()) {
1359: war.delete();
1360: } else if (dir.exists()) {
1361: undeployDir(dir);
1362: } else {
1363: xml.delete();
1364: }
1365: // Perform new deployment
1366: check(path);
1367: } finally {
1368: removeServiced(path);
1369: }
1370: }
1371: writer.println(sm.getString("managerServlet.undeployed",
1372: displayPath));
1373: } catch (Throwable t) {
1374: log("ManagerServlet.undeploy[" + displayPath + "]", t);
1375: writer.println(sm.getString("managerServlet.exception", t
1376: .toString()));
1377: }
1378:
1379: }
1380:
1381: // -------------------------------------------------------- Support Methods
1382:
1383: /**
1384: * Given a context path, get the config file name.
1385: */
1386: protected String getConfigFile(String path) {
1387: String basename = null;
1388: if (path.equals("")) {
1389: basename = "ROOT";
1390: } else {
1391: basename = path.substring(1).replace('/', '#');
1392: }
1393: return (basename);
1394: }
1395:
1396: /**
1397: * Given a context path, get the config file name.
1398: */
1399: protected String getDocBase(String path) {
1400: String basename = null;
1401: if (path.equals("")) {
1402: basename = "ROOT";
1403: } else {
1404: basename = path.substring(1);
1405: }
1406: return (basename);
1407: }
1408:
1409: /**
1410: * Return a File object representing the "application root" directory
1411: * for our associated Host.
1412: */
1413: protected File getAppBase() {
1414:
1415: if (appBase != null) {
1416: return appBase;
1417: }
1418:
1419: File file = new File(host.getAppBase());
1420: if (!file.isAbsolute())
1421: file = new File(System.getProperty("catalina.base"), host
1422: .getAppBase());
1423: try {
1424: appBase = file.getCanonicalFile();
1425: } catch (IOException e) {
1426: appBase = file;
1427: }
1428: return (appBase);
1429:
1430: }
1431:
1432: /**
1433: * Invoke the isDeployed method on the deployer.
1434: */
1435: protected boolean isDeployed(String name) throws Exception {
1436: String[] params = { name };
1437: String[] signature = { "java.lang.String" };
1438: Boolean result = (Boolean) mBeanServer.invoke(oname,
1439: "isDeployed", params, signature);
1440: return result.booleanValue();
1441: }
1442:
1443: /**
1444: * Invoke the check method on the deployer.
1445: */
1446: protected void check(String name) throws Exception {
1447: String[] params = { name };
1448: String[] signature = { "java.lang.String" };
1449: mBeanServer.invoke(oname, "check", params, signature);
1450: }
1451:
1452: /**
1453: * Invoke the isServiced method on the deployer.
1454: */
1455: protected boolean isServiced(String name) throws Exception {
1456: String[] params = { name };
1457: String[] signature = { "java.lang.String" };
1458: Boolean result = (Boolean) mBeanServer.invoke(oname,
1459: "isServiced", params, signature);
1460: return result.booleanValue();
1461: }
1462:
1463: /**
1464: * Invoke the addServiced method on the deployer.
1465: */
1466: protected void addServiced(String name) throws Exception {
1467: String[] params = { name };
1468: String[] signature = { "java.lang.String" };
1469: mBeanServer.invoke(oname, "addServiced", params, signature);
1470: }
1471:
1472: /**
1473: * Invoke the removeServiced method on the deployer.
1474: */
1475: protected void removeServiced(String name) throws Exception {
1476: String[] params = { name };
1477: String[] signature = { "java.lang.String" };
1478: mBeanServer.invoke(oname, "removeServiced", params, signature);
1479: }
1480:
1481: /**
1482: * Delete the specified directory, including all of its contents and
1483: * subdirectories recursively.
1484: *
1485: * @param dir File object representing the directory to be deleted
1486: */
1487: protected void undeployDir(File dir) {
1488:
1489: String files[] = dir.list();
1490: if (files == null) {
1491: files = new String[0];
1492: }
1493: for (int i = 0; i < files.length; i++) {
1494: File file = new File(dir, files[i]);
1495: if (file.isDirectory()) {
1496: undeployDir(file);
1497: } else {
1498: file.delete();
1499: }
1500: }
1501: dir.delete();
1502:
1503: }
1504:
1505: /**
1506: * Upload the WAR file included in this request, and store it at the
1507: * specified file location.
1508: *
1509: * @param request The servlet request we are processing
1510: * @param war The file into which we should store the uploaded WAR
1511: *
1512: * @exception IOException if an I/O error occurs during processing
1513: */
1514: protected void uploadWar(HttpServletRequest request, File war)
1515: throws IOException {
1516:
1517: war.delete();
1518: ServletInputStream istream = null;
1519: BufferedOutputStream ostream = null;
1520: try {
1521: istream = request.getInputStream();
1522: ostream = new BufferedOutputStream(
1523: new FileOutputStream(war), 1024);
1524: byte buffer[] = new byte[1024];
1525: while (true) {
1526: int n = istream.read(buffer);
1527: if (n < 0) {
1528: break;
1529: }
1530: ostream.write(buffer, 0, n);
1531: }
1532: ostream.flush();
1533: ostream.close();
1534: ostream = null;
1535: istream.close();
1536: istream = null;
1537: } catch (IOException e) {
1538: war.delete();
1539: throw e;
1540: } finally {
1541: if (ostream != null) {
1542: try {
1543: ostream.close();
1544: } catch (Throwable t) {
1545: ;
1546: }
1547: ostream = null;
1548: }
1549: if (istream != null) {
1550: try {
1551: istream.close();
1552: } catch (Throwable t) {
1553: ;
1554: }
1555: istream = null;
1556: }
1557: }
1558:
1559: }
1560:
1561: /**
1562: * Copy the specified file or directory to the destination.
1563: *
1564: * @param src File object representing the source
1565: * @param dest File object representing the destination
1566: */
1567: public static boolean copy(File src, File dest) {
1568: boolean result = false;
1569: try {
1570: if (src != null
1571: && !src.getCanonicalPath().equals(
1572: dest.getCanonicalPath())) {
1573: result = copyInternal(src, dest, new byte[4096]);
1574: }
1575: } catch (IOException e) {
1576: e.printStackTrace();
1577: }
1578: return result;
1579: }
1580:
1581: /**
1582: * Copy the specified file or directory to the destination.
1583: *
1584: * @param src File object representing the source
1585: * @param dest File object representing the destination
1586: */
1587: public static boolean copyInternal(File src, File dest, byte[] buf) {
1588:
1589: boolean result = true;
1590:
1591: String files[] = null;
1592: if (src.isDirectory()) {
1593: files = src.list();
1594: result = dest.mkdir();
1595: } else {
1596: files = new String[1];
1597: files[0] = "";
1598: }
1599: if (files == null) {
1600: files = new String[0];
1601: }
1602: for (int i = 0; (i < files.length) && result; i++) {
1603: File fileSrc = new File(src, files[i]);
1604: File fileDest = new File(dest, files[i]);
1605: if (fileSrc.isDirectory()) {
1606: result = copyInternal(fileSrc, fileDest, buf);
1607: } else {
1608: FileInputStream is = null;
1609: FileOutputStream os = null;
1610: try {
1611: is = new FileInputStream(fileSrc);
1612: os = new FileOutputStream(fileDest);
1613: int len = 0;
1614: while (true) {
1615: len = is.read(buf);
1616: if (len == -1)
1617: break;
1618: os.write(buf, 0, len);
1619: }
1620: } catch (IOException e) {
1621: e.printStackTrace();
1622: result = false;
1623: } finally {
1624: if (is != null) {
1625: try {
1626: is.close();
1627: } catch (IOException e) {
1628: }
1629: }
1630: if (os != null) {
1631: try {
1632: os.close();
1633: } catch (IOException e) {
1634: }
1635: }
1636: }
1637: }
1638: }
1639: return result;
1640:
1641: }
1642:
1643: }
|