/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.catalina.manager;
/** * Servlet that enables remote management of the web applications installed within the same virtual host as this web * application is. Normally, this functionality will be protected by a security constraint in the web application * deployment descriptor. However, this requirement can be relaxed during testing. * <p> * This servlet examines the value returned by <code>getPathInfo()</code> and related query parameters to determine what * action is being requested. The following actions and parameters (starting after the servlet path) are supported: * <ul> * <li><b>/deploy?config={config-url}</b> - Install and start a new web application, based on the contents of the * context configuration file found at the specified URL. The <code>docBase</code> attribute of the context * configuration file is used to locate the actual WAR or directory containing the application.</li> * <li><b>/deploy?config={config-url}&war={war-url}/</b> - Install and start a new web application, based on the * contents of the context configuration file found at <code>{config-url}</code>, overriding the <code>docBase</code> * attribute with the contents of the web application archive found at <code>{war-url}</code>.</li> * <li><b>/deploy?path=/xxx&war={war-url}</b> - Install and start a new web application attached to context path * <code>/xxx</code>, based on the contents of the web application archive found at the specified URL.</li> * <li><b>/list</b> - List the context paths of all currently installed web applications for this virtual host. Each * context will be listed with the following format <code>path:status:sessions</code>. Where path is the context path. * Status is either running or stopped. Sessions is the number of active Sessions.</li> * <li><b>/reload?path=/xxx</b> - Reload the Java classes and resources for the application at the specified path.</li> * <li><b>/resources?type=xxxx</b> - Enumerate the available global JNDI resources, optionally limited to those of the * specified type (fully qualified Java class name), if available.</li> * <li><b>/serverinfo</b> - Display system OS and JVM properties. * <li><b>/sessions</b> - Deprecated. Use expire. * <li><b>/expire?path=/xxx</b> - List session idle time information about the web application attached to context path * <code>/xxx</code> for this virtual host.</li> * <li><b>/expire?path=/xxx&idle=mm</b> - Expire sessions for the context path <code>/xxx</code> which were idle for * at least mm minutes.</li> * <li><b>/sslConnectorCiphers</b> - Display diagnostic info on SSL/TLS ciphers that are currently configured for each * connector. * <li><b>/start?path=/xxx</b> - Start the web application attached to context path <code>/xxx</code> for this virtual * host.</li> * <li><b>/stop?path=/xxx</b> - Stop the web application attached to context path <code>/xxx</code> for this virtual * host.</li> * <li><b>/threaddump</b> - Write a JVM thread dump.</li> * <li><b>/undeploy?path=/xxx</b> - Shutdown and remove the web application attached to context path <code>/xxx</code> * for this virtual host, and remove the underlying WAR file or document base directory. (<em>NOTE</em> - This is only * allowed if the WAR file or document base is stored in the <code>appBase</code> directory of this host, typically as a * result of being placed there via the <code>/deploy</code> command.</li> * <li><b>/vminfo</b> - Write some VM info.</li> * <li><b>/save</b> - Save the current server configuration to server.xml</li> * <li><b>/save?path=/xxx</b> - Save the context configuration for the web application deployed with path * <code>/xxx</code> to an appropriately named context.xml file in the <code>xmlBase</code> for the associated * Host.</li> * </ul> * <p> * Use <code>path=/</code> for the ROOT context. * </p> * <p> * The syntax of the URL for a web application archive must conform to one of the following patterns to be successfully * deployed: * </p> * <ul> * <li><b>file:/absolute/path/to/a/directory</b> - You can specify the absolute path of a directory that contains the * unpacked version of a web application. This directory will be attached to the context path you specify without any * changes.</li> * </ul> * <p> * <b>NOTE</b> - Attempting to reload or remove the application containing this servlet itself will not succeed. * Therefore, this servlet should generally be deployed as a separate web application within the virtual host to be * managed. * <p> * The following servlet initialization parameters are recognized: * <ul> * <li><b>debug</b> - The debugging detail level that controls the amount of information that is logged by this servlet. * Default is zero. * </ul> * * @author Craig R. McClanahan * @author Remy Maucherat
*/ publicclass ManagerServlet extends HttpServlet implements ContainerServlet {
// Retrieve the MBean server
mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
}
// --------------------------------------------------------- Public Methods
/** * Finalize this servlet.
*/
@Override publicvoid destroy() {
// No actions necessary
}
/** * Process a GET request for the specified resource. * * @param request The servlet request we are processing * @param response The servlet response we are creating * * @exception IOException if an input/output error occurs * @exception ServletException if a servlet-specified error occurs
*/
@Override publicvoid doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// Prepare our output writer to generate the response message
response.setContentType("text/plain; charset=" + Constants.CHARSET); // Stop older versions of IE thinking they know best. We set text/plain // in the line above for a reason. IE's behaviour is unwanted at best // and dangerous at worst.
response.setHeader("X-Content-Type-Options", "nosniff");
PrintWriter writer = response.getWriter();
// Finish up the response
writer.flush();
writer.close();
}
/** * Process a PUT request for the specified resource. * * @param request The servlet request we are processing * @param response The servlet response we are creating * * @exception IOException if an input/output error occurs * @exception ServletException if a servlet-specified error occurs
*/
@Override publicvoid doPut(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// Identify the request parameters that we need
String command = request.getPathInfo(); if (command == null) {
command = request.getServletPath();
}
String path = request.getParameter("path");
ContextName cn = null; if (path != null) {
cn = new ContextName(path, request.getParameter("version"));
}
String config = request.getParameter("config");
String tag = request.getParameter("tag"); boolean update = false; if (request.getParameter("update") != null && request.getParameter("update").equals("true")) {
update = true;
}
// Prepare our output writer to generate the response message
response.setContentType("text/plain;charset=" + Constants.CHARSET); // Stop older versions of IE thinking they know best. We set text/plain // in the line above for a reason. IE's behaviour is unwanted at best // and dangerous at worst.
response.setHeader("X-Content-Type-Options", "nosniff");
PrintWriter writer = response.getWriter();
// Process the requested command if (command == null) {
writer.println(smClient.getString("managerServlet.noCommand"));
} elseif (command.equals("/deploy")) {
deploy(writer, config, cn, tag, update, request, smClient);
} else {
writer.println(smClient.getString("managerServlet.unknownCommand", command));
}
// Finish up the response
writer.flush();
writer.close();
// Ensure that our ContainerServlet properties have been set if (wrapper == null || context == null) { thrownew UnavailableException(sm.getString("managerServlet.noWrapper"));
}
// Set our properties from the initialization parameters
String value = null; try {
value = getServletConfig().getInitParameter("debug");
debug = Integer.parseInt(value);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
// Acquire global JNDI resources if available
Server server = ((Engine) host.getParent()).getService().getServer(); if (server != null) {
global = server.getGlobalNamingContext();
}
// Calculate the directory into which we will be deploying applications
versioned = (File) getServletContext().getAttribute(ServletContext.TEMPDIR);
configBase = new File(context.getCatalinaBase(), "conf");
Container container = context;
Container host = null;
Container engine = null; while (container != null) { if (container instanceof Host) {
host = container;
} if (container instanceof Engine) {
engine = container;
}
container = container.getParent();
} if (engine != null) {
configBase = new File(configBase, engine.getName());
} if (host != null) {
configBase = new File(configBase, host.getName());
} // Note: The directory must exist for this to work.
// Log debugging messages as necessary if (debug >= 1) {
log("init: Associated with Deployer '" + oname + "'"); if (global != null) {
log("init: Global resources are available");
}
}
/** * Store server configuration. * * @param writer Destination for any user message(s) during this operation * @param path Optional context path to save * @param smClient i18n support for current client's locale
*/ protectedsynchronizedvoid save(PrintWriter writer, String path, StringManager smClient) {
ObjectName storeConfigOname; try { // Note: Hard-coded domain used since this object is per Server/JVM
storeConfigOname = new ObjectName("Catalina:type=StoreConfig");
} catch (MalformedObjectNameException e) { // Should never happen. The name above is valid.
log(sm.getString("managerServlet.exception"), e);
writer.println(smClient.getString("managerServlet.exception", e.toString())); return;
}
if (!mBeanServer.isRegistered(storeConfigOname)) {
writer.println(smClient.getString("managerServlet.storeConfig.noMBean", storeConfigOname)); return;
}
/** * Deploy a web application archive (included in the current request) at the specified context path. * * @param writer Writer to render results to * @param config URL of the context configuration file to be installed * @param cn Name of the application to be installed * @param tag Tag to be associated with the webapp * @param update Flag that indicates that any existing app should be replaced * @param request Servlet request we are processing * @param smClient i18n messages using the locale of the client
*/ protectedvoid deploy(PrintWriter writer, String config, ContextName cn, String tag, boolean update,
HttpServletRequest request, StringManager smClient) {
if (debug >= 1) { if (config == null) {
log("deploy: Deploying web application '" + cn + "'");
} else {
log("deploy: Deploying web application '" + cn + "' " + "with context configuration at '" + config + "'");
}
}
// Validate the requested context path if (!validateContextName(cn, writer, smClient)) { return;
}
String name = cn.getName();
String baseName = cn.getBaseName();
String displayPath = cn.getDisplayName();
// If app exists deployment can only proceed if update is true // Note existing WAR will be deleted and then replaced
Context context = (Context) host.findChild(name); if (context != null && !update) {
writer.println(smClient.getString("managerServlet.alreadyContext", displayPath)); return;
}
File deployedWar = new File(host.getAppBaseFile(), baseName + ".war");
// Determine full path for uploaded WAR
File uploadedWar; if (tag == null) { if (update) { // Append ".tmp" to the file name so it won't get deployed if auto // deployment is enabled. It also means the old war won't get // deleted if the upload fails
uploadedWar = new File(deployedWar.getAbsolutePath() + ".tmp"); if (uploadedWar.exists() && !uploadedWar.delete()) {
writer.println(smClient.getString("managerServlet.deleteFail", uploadedWar));
}
} else {
uploadedWar = deployedWar;
}
} else {
File uploadPath = new File(versioned, tag); if (!uploadPath.mkdirs() && !uploadPath.isDirectory()) {
writer.println(smClient.getString("managerServlet.mkdirFail", uploadPath)); return;
}
uploadedWar = new File(uploadPath, baseName + ".war");
} if (debug >= 2) {
log("Uploading WAR file to " + uploadedWar);
}
try { if (tryAddServiced(name)) { try { if (config != null) { if (!configBase.mkdirs() && !configBase.isDirectory()) {
writer.println(smClient.getString("managerServlet.mkdirFail", configBase)); return;
} if (ExpandWar.copy(new File(config), new File(configBase, baseName + ".xml")) == false) { thrownew Exception(sm.getString("managerServlet.copyError", config));
}
} // Upload WAR
uploadWar(writer, request, uploadedWar, smClient); if (update && tag == null) { if (deployedWar.exists() && !deployedWar.delete()) {
writer.println(smClient.getString("managerServlet.deleteFail", deployedWar)); return;
} // Rename uploaded WAR file if (!uploadedWar.renameTo(deployedWar)) {
writer.println(smClient.getString("managerServlet.renameFail", uploadedWar, deployedWar)); return;
}
} if (tag != null) { // Copy WAR to the host's appBase
ExpandWar.copy(uploadedWar, deployedWar);
}
} finally {
removeServiced(name);
} // Perform new deployment
check(name);
} else {
writer.println(smClient.getString("managerServlet.inService", displayPath));
}
} catch (Exception e) {
log(sm.getString("managerServlet.error.deploy", displayPath), e);
writer.println(smClient.getString("managerServlet.exception", e.toString())); return;
}
/** * Install an application for the specified path from the specified web application archive. * * @param writer Writer to render results to * @param tag Revision tag to deploy from * @param cn Name of the application to be installed * @param smClient i18n messages using the locale of the client
*/ protectedvoid deploy(PrintWriter writer, ContextName cn, String tag, StringManager smClient) {
// NOTE: It is assumed that update is always true in this method.
// Validate the requested context path if (!validateContextName(cn, writer, smClient)) { return;
}
/** * Install an application for the specified path from the specified web application archive. * * @param writer Writer to render results to * @param config URL of the context configuration file to be installed * @param cn Name of the application to be installed * @param war URL of the web application archive to be installed * @param update true to override any existing webapp on the path * @param smClient i18n messages using the locale of the client
*/ protectedvoid deploy(PrintWriter writer, String config, ContextName cn, String war, boolean update,
StringManager smClient) {
if (config != null && config.length() == 0) {
config = null;
} if (war != null && war.length() == 0) {
war = null;
}
if (debug >= 1) { if (config != null) { if (war != null) {
log("install: Installing context configuration at '" + config + "' from '" + war + "'");
} else {
log("install: Installing context configuration at '" + config + "'");
}
} else { if (cn != null) {
log("install: Installing web application '" + cn + "' from '" + war + "'");
} else {
log("install: Installing web application from '" + war + "'");
}
}
}
if (!validateContextName(cn, writer, smClient)) { return;
}
@SuppressWarnings("null") // checked in call above
String name = cn.getName();
String baseName = cn.getBaseName();
String displayPath = cn.getDisplayName();
// If app exists deployment can only proceed if update is true // Note existing files will be deleted and then replaced
Context context = (Context) host.findChild(name); if (context != null && !update) {
writer.println(smClient.getString("managerServlet.alreadyContext", displayPath)); return;
}
if (config != null && config.startsWith("file:")) {
config = config.substring("file:".length());
} if (war != null && war.startsWith("file:")) {
war = war.substring("file:".length());
}
try { if (tryAddServiced(name)) { try { if (config != null) { if (!configBase.mkdirs() && !configBase.isDirectory()) {
writer.println(smClient.getString("managerServlet.mkdirFail", configBase)); return;
}
File localConfigFile = new File(configBase, baseName + ".xml");
File configFile = new File(config); // Skip delete and copy if source == destination if (!configFile.getCanonicalPath().equals(localConfigFile.getCanonicalPath())) { if (localConfigFile.isFile() && !localConfigFile.delete()) {
writer.println(smClient.getString("managerServlet.deleteFail", localConfigFile)); return;
}
ExpandWar.copy(configFile, localConfigFile);
}
} if (war != null) {
File localWarFile; if (war.endsWith(".war")) {
localWarFile = new File(host.getAppBaseFile(), baseName + ".war");
} else {
localWarFile = new File(host.getAppBaseFile(), baseName);
}
File warFile = new File(war); // Skip delete and copy if source == destination if (!warFile.getCanonicalPath().equals(localWarFile.getCanonicalPath())) { if (localWarFile.exists() && !ExpandWar.delete(localWarFile)) {
writer.println(smClient.getString("managerServlet.deleteFail", localWarFile)); return;
}
ExpandWar.copy(warFile, localWarFile);
}
}
} finally {
removeServiced(name);
} // Perform new deployment
check(name);
} else {
writer.println(smClient.getString("managerServlet.inService", displayPath));
}
writeDeployResult(writer, smClient, name, displayPath);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log(sm.getString("managerServlet.error.deploy", displayPath), t);
writer.println(smClient.getString("managerServlet.exception", t.toString()));
}
/** * Render a list of the currently active Contexts in our virtual host. * * @param writer Writer to render to * @param smClient i18n support for current client's locale
*/ protectedvoid list(PrintWriter writer, StringManager smClient) {
if (debug >= 1) {
log("list: Listing contexts for virtual host '" + host.getName() + "'");
}
writer.println(smClient.getString("managerServlet.listed", host.getName()));
Container[] contexts = host.findChildren(); for (Container container : contexts) {
Context context = (Context) container; if (context != null) {
String displayPath = context.getPath(); if (displayPath.equals("")) {
displayPath = "/";
}
List<String> parts = null; if (context.getState().isAvailable()) {
parts = Arrays.asList(displayPath, "running", "" + context.getManager().findSessions().length,
context.getDocBase());
} else {
parts = Arrays.asList(displayPath, "stopped", "0", context.getDocBase());
}
writer.println(StringUtils.join(parts, ':'));
}
}
}
/** * Reload the web application at the specified context path. * * @param writer Writer to render to * @param cn Name of the application to be restarted * @param smClient i18n support for current client's locale
*/ protectedvoid reload(PrintWriter writer, ContextName cn, StringManager smClient) {
if (debug >= 1) {
log("restart: Reloading web application '" + cn + "'");
}
if (!validateContextName(cn, writer, smClient)) { return;
}
try {
Context context = (Context) host.findChild(cn.getName()); if (context == null) {
writer.println(
smClient.getString("managerServlet.noContext", Escape.htmlElementContent(cn.getDisplayName()))); return;
} // It isn't possible for the manager to reload itself if (context.getName().equals(this.context.getName())) {
writer.println(smClient.getString("managerServlet.noSelf")); return;
}
context.reload();
writer.println(smClient.getString("managerServlet.reloaded", cn.getDisplayName()));
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log(sm.getString("managerServlet.error.reload", cn.getDisplayName()), t);
writer.println(smClient.getString("managerServlet.exception", t.toString()));
}
}
/** * Render a list of available global JNDI resources. * * @param writer Writer to render to * @param type Fully qualified class name of the resource type of interest, or <code>null</code> to list * resources of all types * @param smClient i18n support for current client's locale
*/ protectedvoid resources(PrintWriter writer, String type, StringManager smClient) {
if (debug >= 1) { if (type != null) {
log("resources: Listing resources of type " + type);
} else {
log("resources: Listing resources of all types");
}
}
// Is the global JNDI resources context available? if (global == null) {
writer.println(smClient.getString("managerServlet.noGlobal")); return;
}
// Enumerate the global JNDI resources of the requested type if (type != null) {
writer.println(smClient.getString("managerServlet.resourcesType", type));
} else {
writer.println(smClient.getString("managerServlet.resourcesAll"));
}
/** * List the resources of the given context. * * @param writer Writer to render to * @param prefix Path for recursion * @param namingContext The naming context for lookups * @param type Fully qualified class name of the resource type of interest, or <code>null</code> to list * resources of all types * @param smClient i18n support for current client's locale
*/ protectedvoid printResources(PrintWriter writer, String prefix, javax.naming.Context namingContext, String type,
StringManager smClient) { try {
NamingEnumeration<Binding> items = namingContext.listBindings(""); while (items.hasMore()) {
Binding item = items.next();
Object obj = item.getObject(); if (obj instanceof javax.naming.Context) {
printResources(writer, prefix + item.getName() + "/", (javax.naming.Context) obj, type, smClient);
} else { if (type != null && (obj == null || !IntrospectionUtils.isInstance(obj.getClass(), type))) { continue;
}
writer.print(prefix + item.getName());
writer.print(':');
writer.print(item.getClassName()); // Do we want a description if available?
writer.println();
}
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log(sm.getString("managerServlet.error.resources", type), t);
writer.println(smClient.getString("managerServlet.exception", t.toString()));
}
}
/** * Writes System OS and JVM properties. * * @param writer Writer to render to * @param smClient i18n support for current client's locale
*/ protectedvoid serverinfo(PrintWriter writer, StringManager smClient) { if (debug >= 1) {
log("serverinfo");
} try {
writer.println(smClient.getString("managerServlet.serverInfo", ServerInfo.getServerInfo(),
System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch"),
System.getProperty("java.runtime.version"), System.getProperty("java.vm.vendor")));
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log(sm.getString("managerServlet.error.serverInfo"), t);
writer.println(smClient.getString("managerServlet.exception", t.toString()));
}
}
/** * Session information for the web application at the specified context path. Displays a profile of session * thisAccessedTime listing number of sessions for each 10 minute interval up to 10 hours. * * @param writer Writer to render to * @param cn Name of the application to list session information for * @param idle Expire all sessions with idle time > idle for this context * @param smClient i18n support for current client's locale
*/ protectedvoid sessions(PrintWriter writer, ContextName cn, int idle, StringManager smClient) {
if (debug >= 1) {
log("sessions: Session information for web application '" + cn + "'"); if (idle >= 0) {
log("sessions: Session expiration for " + idle + " minutes '" + cn + "'");
}
}
if (!validateContextName(cn, writer, smClient)) { return;
}
String displayPath = cn.getDisplayName();
try {
Context context = (Context) host.findChild(cn.getName()); if (context == null) {
writer.println(smClient.getString("managerServlet.noContext", Escape.htmlElementContent(displayPath))); return;
}
Manager manager = context.getManager(); if (manager == null) {
writer.println(smClient.getString("managerServlet.noManager", Escape.htmlElementContent(displayPath))); return;
} int maxCount = 60; int histoInterval = 1; int maxInactiveInterval = context.getSessionTimeout(); if (maxInactiveInterval > 0) {
histoInterval = maxInactiveInterval / maxCount; if (histoInterval * maxCount < maxInactiveInterval) {
histoInterval++;
} if (0 == histoInterval) {
histoInterval = 1;
}
maxCount = maxInactiveInterval / histoInterval; if (histoInterval * maxCount < maxInactiveInterval) {
maxCount++;
}
}
writer.println(smClient.getString("managerServlet.sessions", displayPath));
writer.println(smClient.getString("managerServlet.sessiondefaultmax", "" + maxInactiveInterval));
Session[] sessions = manager.findSessions(); int[] timeout = newint[maxCount + 1]; int notimeout = 0; int expired = 0; for (Session session : sessions) { int time = (int) (session.getIdleTimeInternal() / 1000L); if (idle >= 0 && time >= idle * 60) {
session.expire();
expired++;
}
time = time / 60 / histoInterval; if (time < 0) {
notimeout++;
} elseif (time >= maxCount) {
timeout[maxCount]++;
} else {
timeout[time]++;
}
} if (timeout[0] > 0) {
writer.println(
smClient.getString("managerServlet.sessiontimeout", "<" + histoInterval, "" + timeout[0]));
} for (int i = 1; i < maxCount; i++) { if (timeout[i] > 0) {
writer.println(smClient.getString("managerServlet.sessiontimeout", "" + i * histoInterval + " - <" + (i + 1) * histoInterval, "" + timeout[i]));
}
} if (timeout[maxCount] > 0) {
writer.println(smClient.getString("managerServlet.sessiontimeout", ">=" + maxCount * histoInterval, "" + timeout[maxCount]));
} if (notimeout > 0) {
writer.println(smClient.getString("managerServlet.sessiontimeout.unlimited", "" + notimeout));
} if (idle >= 0) {
writer.println(smClient.getString("managerServlet.sessiontimeout.expired", ">" + idle, "" + expired));
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log(sm.getString("managerServlet.error.sessions", displayPath), t);
writer.println(smClient.getString("managerServlet.exception", t.toString()));
}
}
/** * Extract the expiration request parameter * * @param writer Writer to render to * @param cn Name of the application to list session information for * @param req The Servlet request * @param smClient i18n support for current client's locale
*/ protectedvoid expireSessions(PrintWriter writer, ContextName cn, HttpServletRequest req, StringManager smClient) { int idle = -1;
String idleParam = req.getParameter("idle"); if (idleParam != null) { try {
idle = Integer.parseInt(idleParam);
} catch (NumberFormatException e) {
log(sm.getString("managerServlet.error.idleParam", idleParam));
}
}
sessions(writer, cn, idle, smClient);
}
/** * Start the web application at the specified context path. * * @param writer Writer to render to * @param cn Name of the application to be started * @param smClient i18n support for current client's locale
*/ protectedvoid start(PrintWriter writer, ContextName cn, StringManager smClient) {
if (debug >= 1) {
log("start: Starting web application '" + cn + "'");
}
if (!validateContextName(cn, writer, smClient)) { return;
}
/** * Stop the web application at the specified context path. * * @param writer Writer to render to * @param cn Name of the application to be stopped * @param smClient i18n support for current client's locale
*/ protectedvoid stop(PrintWriter writer, ContextName cn, StringManager smClient) {
if (debug >= 1) {
log("stop: Stopping web application '" + cn + "'");
}
if (!validateContextName(cn, writer, smClient)) { return;
}
String displayPath = cn.getDisplayName();
try {
Context context = (Context) host.findChild(cn.getName()); if (context == null) {
writer.println(smClient.getString("managerServlet.noContext", Escape.htmlElementContent(displayPath))); return;
} // It isn't possible for the manager to stop itself if (context.getName().equals(this.context.getName())) {
writer.println(smClient.getString("managerServlet.noSelf")); return;
}
context.stop();
writer.println(smClient.getString("managerServlet.stopped", displayPath));
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log(sm.getString("managerServlet.error.stop", displayPath), t);
writer.println(smClient.getString("managerServlet.exception", t.toString()));
}
}
/** * Undeploy the web application at the specified context path. * * @param writer Writer to render to * @param cn Name of the application to be removed * @param smClient i18n support for current client's locale
*/ protectedvoid undeploy(PrintWriter writer, ContextName cn, StringManager smClient) {
if (debug >= 1) {
log("undeploy: Undeploying web application at '" + cn + "'");
}
if (!validateContextName(cn, writer, smClient)) { return;
}
// Validate the Context of the specified application
Context context = (Context) host.findChild(name); if (context == null) {
writer.println(smClient.getString("managerServlet.noContext", Escape.htmlElementContent(displayPath))); return;
}
if (!isDeployed(name)) {
writer.println(
smClient.getString("managerServlet.notDeployed", Escape.htmlElementContent(displayPath))); return;
}
if (tryAddServiced(name)) { try { // Try to stop the context first to be nicer
context.stop();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
} try {
File war = new File(host.getAppBaseFile(), baseName + ".war");
File dir = new File(host.getAppBaseFile(), baseName);
File xml = new File(configBase, baseName + ".xml"); if (war.exists() && !war.delete()) {
writer.println(smClient.getString("managerServlet.deleteFail", war)); return;
} elseif (dir.exists() && !ExpandWar.delete(dir, false)) {
writer.println(smClient.getString("managerServlet.deleteFail", dir)); return;
} elseif (xml.exists() && !xml.delete()) {
writer.println(smClient.getString("managerServlet.deleteFail", xml)); return;
}
} finally {
removeServiced(name);
} // Perform new deployment
check(name);
} else {
writer.println(smClient.getString("managerServlet.inService", displayPath));
}
writer.println(smClient.getString("managerServlet.undeployed", displayPath));
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log(sm.getString("managerServlet.error.undeploy", displayPath), t);
writer.println(smClient.getString("managerServlet.exception", t.toString()));
}
}
// -------------------------------------------------------- Support Methods
/** * Invoke the isDeployed method on the deployer. * * @param name The webapp name * * @return <code>true</code> if a webapp with that name is deployed * * @throws Exception Propagate JMX invocation error
*/ protectedboolean isDeployed(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" }; Boolean result = (Boolean) mBeanServer.invoke(oname, "isDeployed", params, signature); return result.booleanValue();
}
/** * Invoke the check method on the deployer. * * @param name The webapp name * * @throws Exception Propagate JMX invocation error
*/ protectedvoid check(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" };
mBeanServer.invoke(oname, "check", params, signature);
}
/** * Attempt to mark a context as being serviced * * @param name The context name * * @return {@code true} if the application was marked as being serviced and {@code false} if the application was * already marked as being serviced * * @throws Exception Error invoking the deployer
*/ protectedboolean tryAddServiced(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" }; Boolean result = (Boolean) mBeanServer.invoke(oname, "tryAddServiced", params, signature); return result.booleanValue();
}
/** * Invoke the removeServiced method on the deployer. * * @param name The webapp name * * @throws Exception Propagate JMX invocation error
*/ protectedvoid removeServiced(String name) throws Exception {
String[] params = { name };
String[] signature = { "java.lang.String" };
mBeanServer.invoke(oname, "removeServiced", params, signature);
}
/** * Upload the WAR file included in this request, and store it at the specified file location. * * @param writer Writer to render to * @param request The servlet request we are processing * @param war The file into which we should store the uploaded WAR * @param smClient The StringManager used to construct i18n messages based on the Locale of the client * * @exception IOException if an I/O error occurs during processing
*/ protectedvoid uploadWar(PrintWriter writer, HttpServletRequest request, File war, StringManager smClient) throws IOException {
// ContextName should be non-null with a path that is empty or starts // with / if (cn != null && (cn.getPath().startsWith("/") || cn.getPath().equals(""))) { returntrue;
}
protected Map<String,List<String>> getConnectorCiphers(StringManager smClient) {
Map<String,List<String>> result = new HashMap<>();
Connector connectors[] = getConnectors(); for (Connector connector : connectors) { if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler().findSslHostConfigs(); for (SSLHostConfig sslHostConfig : sslHostConfigs) {
String name = connector.toString() + "-" + sslHostConfig.getHostName(); /* Add cipher list, keep order but remove duplicates */
result.put(name, new ArrayList<>(new LinkedHashSet<>(Arrays.asList(sslHostConfig.getEnabledCiphers()))));
}
} else {
ArrayList<String> cipherList = new ArrayList<>(1);
cipherList.add(smClient.getString("managerServlet.notSslConnector"));
result.put(connector.toString(), cipherList);
}
} return result;
}
protected Map<String,List<String>> getConnectorCerts(StringManager smClient) {
Map<String,List<String>> result = new HashMap<>();
Connector connectors[] = getConnectors(); for (Connector connector : connectors) { if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler().findSslHostConfigs(); for (SSLHostConfig sslHostConfig : sslHostConfigs) { if (sslHostConfig.getOpenSslContext().longValue() == 0) { // Not set. Must be JSSE based.
Set<SSLHostConfigCertificate> sslHostConfigCerts = sslHostConfig.getCertificates(); for (SSLHostConfigCertificate sslHostConfigCert : sslHostConfigCerts) {
String name = connector.toString() + "-" + sslHostConfig.getHostName() + "-" +
sslHostConfigCert.getType();
List<String> certList = new ArrayList<>();
SSLContext sslContext = sslHostConfigCert.getSslContext();
String alias = sslHostConfigCert.getCertificateKeyAlias(); if (alias == null) {
alias = SSLUtilBase.DEFAULT_KEY_ALIAS;
}
X509Certificate[] certs = sslContext.getCertificateChain(alias); if (certs == null) {
certList.add(smClient.getString("managerServlet.certsNotAvailable"));
} else { for (Certificate cert : certs) {
certList.add(cert.toString());
}
}
result.put(name, certList);
}
} else {
List<String> certList = new ArrayList<>();
--> --------------------
--> maximum size reached
--> --------------------
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.96Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.