| /* |
| * 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; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Set; |
| |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpSession; |
| import javax.servlet.http.Part; |
| |
| import org.apache.catalina.Container; |
| import org.apache.catalina.Context; |
| import org.apache.catalina.DistributedManager; |
| import org.apache.catalina.Manager; |
| import org.apache.catalina.Session; |
| import org.apache.catalina.manager.util.BaseSessionComparator; |
| import org.apache.catalina.manager.util.SessionUtils; |
| import org.apache.catalina.util.ContextName; |
| import org.apache.catalina.util.RequestUtil; |
| import org.apache.catalina.util.ServerInfo; |
| import org.apache.catalina.util.URLEncoder; |
| import org.apache.tomcat.util.res.StringManager; |
| |
| /** |
| * Servlet that enables remote management of the web applications deployed |
| * 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> |
| * The difference between the <code>ManagerServlet</code> and this |
| * Servlet is that this Servlet prints out a HTML interface which |
| * makes it easier to administrate. |
| * <p> |
| * However if you use a software that parses the output of |
| * <code>ManagerServlet</code> you won't be able to upgrade |
| * to this Servlet since the output are not in the |
| * same format ar from <code>ManagerServlet</code> |
| * |
| * @author Bip Thelin |
| * @author Malcolm Edgar |
| * @author Glenn L. Nielsen |
| * @see ManagerServlet |
| */ |
| public final class HTMLManagerServlet extends ManagerServlet { |
| |
| private static final long serialVersionUID = 1L; |
| |
| static final URLEncoder URL_ENCODER; |
| static final String APPLICATION_MESSAGE = "message"; |
| static final String APPLICATION_ERROR = "error"; |
| |
| static final String sessionsListJspPath = "/WEB-INF/jsp/sessionsList.jsp"; |
| static final String sessionDetailJspPath = "/WEB-INF/jsp/sessionDetail.jsp"; |
| static final String connectorCiphersJspPath = "/WEB-INF/jsp/connectorCiphers.jsp"; |
| |
| static { |
| URL_ENCODER = new URLEncoder(); |
| // '/' should not be encoded in context paths |
| URL_ENCODER.addSafeCharacter('/'); |
| } |
| |
| private boolean showProxySessions = false; |
| |
| // --------------------------------------------------------- Public Methods |
| |
| /** |
| * 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 |
| public void doGet(HttpServletRequest request, |
| HttpServletResponse response) |
| throws IOException, ServletException { |
| |
| StringManager smClient = StringManager.getManager( |
| Constants.Package, request.getLocales()); |
| |
| // Identify the request parameters that we need |
| // By obtaining the command from the pathInfo, per-command security can |
| // be configured in web.xml |
| String command = request.getPathInfo(); |
| |
| String path = request.getParameter("path"); |
| ContextName cn = null; |
| if (path != null) { |
| cn = new ContextName(path, request.getParameter("version")); |
| } |
| |
| // Prepare our output writer to generate the response message |
| response.setContentType("text/html; charset=" + Constants.CHARSET); |
| |
| String message = ""; |
| // Process the requested command |
| if (command == null || command.equals("/")) { |
| // No command == list |
| } else if (command.equals("/list")) { |
| // List always displayed - nothing to do here |
| } else if (command.equals("/sessions")) { |
| try { |
| doSessions(cn, request, response, smClient); |
| return; |
| } catch (Exception e) { |
| log("HTMLManagerServlet.sessions[" + cn + "]", e); |
| message = smClient.getString("managerServlet.exception", |
| e.toString()); |
| } |
| } else if (command.equals("/sslConnectorCiphers")) { |
| sslConnectorCiphers(request, response); |
| } else if (command.equals("/upload") || command.equals("/deploy") || |
| command.equals("/reload") || command.equals("/undeploy") || |
| command.equals("/expire") || command.equals("/start") || |
| command.equals("/stop")) { |
| message = |
| smClient.getString("managerServlet.postCommand", command); |
| } else { |
| message = |
| smClient.getString("managerServlet.unknownCommand", command); |
| } |
| |
| list(request, response, message, smClient); |
| } |
| |
| /** |
| * Process a POST 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 |
| public void doPost(HttpServletRequest request, |
| HttpServletResponse response) |
| throws IOException, ServletException { |
| |
| StringManager smClient = StringManager.getManager( |
| Constants.Package, request.getLocales()); |
| |
| // Identify the request parameters that we need |
| // By obtaining the command from the pathInfo, per-command security can |
| // be configured in web.xml |
| String command = request.getPathInfo(); |
| |
| String path = request.getParameter("path"); |
| ContextName cn = null; |
| if (path != null) { |
| cn = new ContextName(path, request.getParameter("version")); |
| } |
| String deployPath = request.getParameter("deployPath"); |
| ContextName deployCn = null; |
| if (deployPath != null) { |
| deployCn = new ContextName(deployPath, |
| request.getParameter("deployVersion")); |
| } |
| String deployConfig = request.getParameter("deployConfig"); |
| String deployWar = request.getParameter("deployWar"); |
| |
| // Prepare our output writer to generate the response message |
| response.setContentType("text/html; charset=" + Constants.CHARSET); |
| |
| String message = ""; |
| |
| if (command == null || command.length() == 0) { |
| // No command == list |
| // List always displayed -> do nothing |
| } else if (command.equals("/upload")) { |
| message = upload(request, smClient); |
| } else if (command.equals("/deploy")) { |
| message = deployInternal(deployConfig, deployCn, deployWar, |
| smClient); |
| } else if (command.equals("/reload")) { |
| message = reload(cn, smClient); |
| } else if (command.equals("/undeploy")) { |
| message = undeploy(cn, smClient); |
| } else if (command.equals("/expire")) { |
| message = expireSessions(cn, request, smClient); |
| } else if (command.equals("/start")) { |
| message = start(cn, smClient); |
| } else if (command.equals("/stop")) { |
| message = stop(cn, smClient); |
| } else if (command.equals("/findleaks")) { |
| message = findleaks(smClient); |
| } else { |
| // Try GET |
| doGet(request,response); |
| return; |
| } |
| |
| list(request, response, message, smClient); |
| } |
| |
| protected String upload(HttpServletRequest request, StringManager smClient) { |
| String message = ""; |
| |
| try { |
| while (true) { |
| Part warPart = request.getPart("deployWar"); |
| if (warPart == null) { |
| message = smClient.getString( |
| "htmlManagerServlet.deployUploadNoFile"); |
| break; |
| } |
| String filename = warPart.getSubmittedFileName(); |
| if (!filename.toLowerCase(Locale.ENGLISH).endsWith(".war")) { |
| message = smClient.getString( |
| "htmlManagerServlet.deployUploadNotWar", filename); |
| break; |
| } |
| // Get the filename if uploaded name includes a path |
| if (filename.lastIndexOf('\\') >= 0) { |
| filename = |
| filename.substring(filename.lastIndexOf('\\') + 1); |
| } |
| if (filename.lastIndexOf('/') >= 0) { |
| filename = |
| filename.substring(filename.lastIndexOf('/') + 1); |
| } |
| |
| // Identify the appBase of the owning Host of this Context |
| // (if any) |
| File file = new File(host.getAppBaseFile(), filename); |
| if (file.exists()) { |
| message = smClient.getString( |
| "htmlManagerServlet.deployUploadWarExists", |
| filename); |
| break; |
| } |
| |
| ContextName cn = new ContextName(filename, true); |
| String name = cn.getName(); |
| |
| if ((host.findChild(name) != null) && !isDeployed(name)) { |
| message = smClient.getString( |
| "htmlManagerServlet.deployUploadInServerXml", |
| filename); |
| break; |
| } |
| |
| if (isServiced(name)) { |
| message = smClient.getString("managerServlet.inService", name); |
| } else { |
| addServiced(name); |
| try { |
| warPart.write(file.getAbsolutePath()); |
| // Perform new deployment |
| check(name); |
| } finally { |
| removeServiced(name); |
| } |
| } |
| break; |
| } |
| } catch(Exception e) { |
| message = smClient.getString |
| ("htmlManagerServlet.deployUploadFail", e.getMessage()); |
| log(message, e); |
| } |
| return message; |
| } |
| |
| /** |
| * Deploy an application for the specified path from the specified |
| * web application archive. |
| * |
| * @param config URL of the context configuration file to be deployed |
| * @param cn Name of the application to be deployed |
| * @param war URL of the web application archive to be deployed |
| * @param smClient internationalized strings |
| * @return message String |
| */ |
| protected String deployInternal(String config, ContextName cn, String war, |
| StringManager smClient) { |
| |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| super.deploy(printWriter, config, cn, war, false, smClient); |
| |
| return stringWriter.toString(); |
| } |
| |
| /** |
| * Render a HTML list of the currently active Contexts in our virtual host, |
| * and memory and server status information. |
| * |
| * @param request The request |
| * @param response The response |
| * @param message a message to display |
| * @param smClient internationalized strings |
| * @throws IOException an IO error occurred |
| */ |
| protected void list(HttpServletRequest request, |
| HttpServletResponse response, |
| String message, |
| StringManager smClient) throws IOException { |
| |
| if (debug >= 1) |
| log("list: Listing contexts for virtual host '" + |
| host.getName() + "'"); |
| |
| PrintWriter writer = response.getWriter(); |
| |
| // HTML Header Section |
| writer.print(Constants.HTML_HEADER_SECTION); |
| |
| // Body Header Section |
| Object[] args = new Object[2]; |
| args[0] = request.getContextPath(); |
| args[1] = smClient.getString("htmlManagerServlet.title"); |
| writer.print(MessageFormat.format |
| (Constants.BODY_HEADER_SECTION, args)); |
| |
| // Message Section |
| args = new Object[3]; |
| args[0] = smClient.getString("htmlManagerServlet.messageLabel"); |
| if (message == null || message.length() == 0) { |
| args[1] = "OK"; |
| } else { |
| args[1] = RequestUtil.filter(message); |
| } |
| writer.print(MessageFormat.format(Constants.MESSAGE_SECTION, args)); |
| |
| // Manager Section |
| args = new Object[9]; |
| args[0] = smClient.getString("htmlManagerServlet.manager"); |
| args[1] = response.encodeURL(request.getContextPath() + "/html/list"); |
| args[2] = smClient.getString("htmlManagerServlet.list"); |
| args[3] = response.encodeURL |
| (request.getContextPath() + "/" + |
| smClient.getString("htmlManagerServlet.helpHtmlManagerFile")); |
| args[4] = smClient.getString("htmlManagerServlet.helpHtmlManager"); |
| args[5] = response.encodeURL |
| (request.getContextPath() + "/" + |
| smClient.getString("htmlManagerServlet.helpManagerFile")); |
| args[6] = smClient.getString("htmlManagerServlet.helpManager"); |
| args[7] = response.encodeURL |
| (request.getContextPath() + "/status"); |
| args[8] = smClient.getString("statusServlet.title"); |
| writer.print(MessageFormat.format(Constants.MANAGER_SECTION, args)); |
| |
| // Apps Header Section |
| args = new Object[7]; |
| args[0] = smClient.getString("htmlManagerServlet.appsTitle"); |
| args[1] = smClient.getString("htmlManagerServlet.appsPath"); |
| args[2] = smClient.getString("htmlManagerServlet.appsVersion"); |
| args[3] = smClient.getString("htmlManagerServlet.appsName"); |
| args[4] = smClient.getString("htmlManagerServlet.appsAvailable"); |
| args[5] = smClient.getString("htmlManagerServlet.appsSessions"); |
| args[6] = smClient.getString("htmlManagerServlet.appsTasks"); |
| writer.print(MessageFormat.format(APPS_HEADER_SECTION, args)); |
| |
| // Apps Row Section |
| // Create sorted map of deployed applications by context name. |
| Container children[] = host.findChildren(); |
| String contextNames[] = new String[children.length]; |
| for (int i = 0; i < children.length; i++) |
| contextNames[i] = children[i].getName(); |
| |
| Arrays.sort(contextNames); |
| |
| String appsStart = smClient.getString("htmlManagerServlet.appsStart"); |
| String appsStop = smClient.getString("htmlManagerServlet.appsStop"); |
| String appsReload = smClient.getString("htmlManagerServlet.appsReload"); |
| String appsUndeploy = |
| smClient.getString("htmlManagerServlet.appsUndeploy"); |
| String appsExpire = smClient.getString("htmlManagerServlet.appsExpire"); |
| String noVersion = "<i>" + |
| smClient.getString("htmlManagerServlet.noVersion") + "</i>"; |
| |
| boolean isHighlighted = true; |
| boolean isDeployed = true; |
| String highlightColor = null; |
| |
| for (String contextName : contextNames) { |
| Context ctxt = (Context) host.findChild(contextName); |
| |
| if (ctxt != null) { |
| // Bugzilla 34818, alternating row colors |
| isHighlighted = !isHighlighted; |
| if(isHighlighted) { |
| highlightColor = "#C3F3C3"; |
| } else { |
| highlightColor = "#FFFFFF"; |
| } |
| |
| String contextPath = ctxt.getPath(); |
| String displayPath = contextPath; |
| if (displayPath.equals("")) { |
| displayPath = "/"; |
| } |
| |
| StringBuilder tmp = new StringBuilder(); |
| tmp.append("path="); |
| tmp.append(URL_ENCODER.encode(displayPath, "UTF-8")); |
| if (ctxt.getWebappVersion().length() > 0) { |
| tmp.append("&version="); |
| tmp.append(URL_ENCODER.encode(ctxt.getWebappVersion(), "UTF-8")); |
| } |
| String pathVersion = tmp.toString(); |
| |
| try { |
| isDeployed = isDeployed(contextName); |
| } catch (Exception e) { |
| // Assume false on failure for safety |
| isDeployed = false; |
| } |
| |
| args = new Object[7]; |
| args[0] = "<a href=\"" + URL_ENCODER.encode(contextPath + "/", "UTF-8") |
| + "\">" + RequestUtil.filter(displayPath) + "</a>"; |
| if ("".equals(ctxt.getWebappVersion())) { |
| args[1] = noVersion; |
| } else { |
| args[1] = RequestUtil.filter(ctxt.getWebappVersion()); |
| } |
| if (ctxt.getDisplayName() == null) { |
| args[2] = " "; |
| } else { |
| args[2] = RequestUtil.filter(ctxt.getDisplayName()); |
| } |
| args[3] = Boolean.valueOf(ctxt.getState().isAvailable()); |
| args[4] = RequestUtil.filter(response.encodeURL(request.getContextPath() + |
| "/html/sessions?" + pathVersion)); |
| Manager manager = ctxt.getManager(); |
| if (manager instanceof DistributedManager && showProxySessions) { |
| args[5] = Integer.valueOf( |
| ((DistributedManager)manager).getActiveSessionsFull()); |
| } else if (manager != null){ |
| args[5] = Integer.valueOf(manager.getActiveSessions()); |
| } else { |
| args[5] = Integer.valueOf(0); |
| } |
| |
| args[6] = highlightColor; |
| |
| writer.print |
| (MessageFormat.format(APPS_ROW_DETAILS_SECTION, args)); |
| |
| args = new Object[14]; |
| args[0] = RequestUtil.filter(response.encodeURL(request |
| .getContextPath() + "/html/start?" + pathVersion)); |
| args[1] = appsStart; |
| args[2] = RequestUtil.filter(response.encodeURL(request |
| .getContextPath() + "/html/stop?" + pathVersion)); |
| args[3] = appsStop; |
| args[4] = RequestUtil.filter(response.encodeURL(request |
| .getContextPath() + "/html/reload?" + pathVersion)); |
| args[5] = appsReload; |
| args[6] = RequestUtil.filter(response.encodeURL(request |
| .getContextPath() + "/html/undeploy?" + pathVersion)); |
| args[7] = appsUndeploy; |
| args[8] = RequestUtil.filter(response.encodeURL(request |
| .getContextPath() + "/html/expire?" + pathVersion)); |
| args[9] = appsExpire; |
| args[10] = smClient.getString("htmlManagerServlet.expire.explain"); |
| if (manager == null) { |
| args[11] = smClient.getString("htmlManagerServlet.noManager"); |
| } else { |
| args[11] = Integer.valueOf(ctxt.getSessionTimeout()); |
| } |
| args[12] = smClient.getString("htmlManagerServlet.expire.unit"); |
| args[13] = highlightColor; |
| |
| if (ctxt.getName().equals(this.context.getName())) { |
| writer.print(MessageFormat.format( |
| MANAGER_APP_ROW_BUTTON_SECTION, args)); |
| } else if (ctxt.getState().isAvailable() && isDeployed) { |
| writer.print(MessageFormat.format( |
| STARTED_DEPLOYED_APPS_ROW_BUTTON_SECTION, args)); |
| } else if (ctxt.getState().isAvailable() && !isDeployed) { |
| writer.print(MessageFormat.format( |
| STARTED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION, args)); |
| } else if (!ctxt.getState().isAvailable() && isDeployed) { |
| writer.print(MessageFormat.format( |
| STOPPED_DEPLOYED_APPS_ROW_BUTTON_SECTION, args)); |
| } else { |
| writer.print(MessageFormat.format( |
| STOPPED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION, args)); |
| } |
| |
| } |
| } |
| |
| // Deploy Section |
| args = new Object[7]; |
| args[0] = smClient.getString("htmlManagerServlet.deployTitle"); |
| args[1] = smClient.getString("htmlManagerServlet.deployServer"); |
| args[2] = response.encodeURL(request.getContextPath() + "/html/deploy"); |
| args[3] = smClient.getString("htmlManagerServlet.deployPath"); |
| args[4] = smClient.getString("htmlManagerServlet.deployConfig"); |
| args[5] = smClient.getString("htmlManagerServlet.deployWar"); |
| args[6] = smClient.getString("htmlManagerServlet.deployButton"); |
| writer.print(MessageFormat.format(DEPLOY_SECTION, args)); |
| |
| args = new Object[4]; |
| args[0] = smClient.getString("htmlManagerServlet.deployUpload"); |
| args[1] = response.encodeURL(request.getContextPath() + "/html/upload"); |
| args[2] = smClient.getString("htmlManagerServlet.deployUploadFile"); |
| args[3] = smClient.getString("htmlManagerServlet.deployButton"); |
| writer.print(MessageFormat.format(UPLOAD_SECTION, args)); |
| |
| // Diagnostics section |
| args = new Object[9]; |
| args[0] = smClient.getString("htmlManagerServlet.diagnosticsTitle"); |
| args[1] = smClient.getString("htmlManagerServlet.diagnosticsLeak"); |
| args[2] = response.encodeURL( |
| request.getContextPath() + "/html/findleaks"); |
| args[3] = smClient.getString("htmlManagerServlet.diagnosticsLeakWarning"); |
| args[4] = smClient.getString("htmlManagerServlet.diagnosticsLeakButton"); |
| args[5] = smClient.getString("htmlManagerServlet.diagnosticsSsl"); |
| args[6] = response.encodeURL( |
| request.getContextPath() + "/html/sslConnectorCiphers"); |
| args[7] = smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCipherButton"); |
| args[8] = smClient.getString("htmlManagerServlet.diagnosticsSslConnectorCipherText"); |
| writer.print(MessageFormat.format(DIAGNOSTICS_SECTION, args)); |
| |
| // Server Header Section |
| args = new Object[9]; |
| args[0] = smClient.getString("htmlManagerServlet.serverTitle"); |
| args[1] = smClient.getString("htmlManagerServlet.serverVersion"); |
| args[2] = smClient.getString("htmlManagerServlet.serverJVMVersion"); |
| args[3] = smClient.getString("htmlManagerServlet.serverJVMVendor"); |
| args[4] = smClient.getString("htmlManagerServlet.serverOSName"); |
| args[5] = smClient.getString("htmlManagerServlet.serverOSVersion"); |
| args[6] = smClient.getString("htmlManagerServlet.serverOSArch"); |
| args[7] = sm.getString("htmlManagerServlet.serverHostname"); |
| args[8] = sm.getString("htmlManagerServlet.serverIPAddress"); |
| writer.print(MessageFormat.format |
| (Constants.SERVER_HEADER_SECTION, args)); |
| |
| // Server Row Section |
| args = new Object[8]; |
| args[0] = ServerInfo.getServerInfo(); |
| args[1] = System.getProperty("java.runtime.version"); |
| args[2] = System.getProperty("java.vm.vendor"); |
| args[3] = System.getProperty("os.name"); |
| args[4] = System.getProperty("os.version"); |
| args[5] = System.getProperty("os.arch"); |
| try { |
| InetAddress address = InetAddress.getLocalHost(); |
| args[6] = address.getHostName(); |
| args[7] = address.getHostAddress(); |
| } catch (UnknownHostException e) { |
| args[6] = "-"; |
| args[7] = "-"; |
| } |
| writer.print(MessageFormat.format(Constants.SERVER_ROW_SECTION, args)); |
| |
| // HTML Tail Section |
| writer.print(Constants.HTML_TAIL_SECTION); |
| |
| // Finish up the response |
| writer.flush(); |
| writer.close(); |
| } |
| |
| /** |
| * Reload the web application at the specified context path. |
| * |
| * @see ManagerServlet#reload(PrintWriter, ContextName, StringManager) |
| * |
| * @param cn Name of the application to be restarted |
| * @param smClient StringManager for the client's locale |
| * @return message String |
| */ |
| protected String reload(ContextName cn, StringManager smClient) { |
| |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| super.reload(printWriter, cn, smClient); |
| |
| return stringWriter.toString(); |
| } |
| |
| /** |
| * Undeploy the web application at the specified context path. |
| * |
| * @see ManagerServlet#undeploy(PrintWriter, ContextName, StringManager) |
| * |
| * @param cn Name of the application to be undeployed |
| * @param smClient StringManager for the client's locale |
| * @return message String |
| */ |
| protected String undeploy(ContextName cn, StringManager smClient) { |
| |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| super.undeploy(printWriter, cn, smClient); |
| |
| return stringWriter.toString(); |
| } |
| |
| /** |
| * Display session information and invoke list. |
| * |
| * @see ManagerServlet#sessions(PrintWriter, ContextName, int, |
| * StringManager) |
| * |
| * @param cn Name of the application to list session information |
| * @param idle Expire all sessions with idle time ≥ idle for this context |
| * @param smClient StringManager for the client's locale |
| * @return message String |
| */ |
| protected String sessions(ContextName cn, int idle, StringManager smClient) { |
| |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| super.sessions(printWriter, cn, idle, smClient); |
| |
| return stringWriter.toString(); |
| } |
| |
| /** |
| * Start the web application at the specified context path. |
| * |
| * @see ManagerServlet#start(PrintWriter, ContextName, StringManager) |
| * |
| * @param cn Name of the application to be started |
| * @param smClient StringManager for the client's locale |
| * @return message String |
| */ |
| protected String start(ContextName cn, StringManager smClient) { |
| |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| super.start(printWriter, cn, smClient); |
| |
| return stringWriter.toString(); |
| } |
| |
| /** |
| * Stop the web application at the specified context path. |
| * |
| * @see ManagerServlet#stop(PrintWriter, ContextName, StringManager) |
| * |
| * @param cn Name of the application to be stopped |
| * @param smClient StringManager for the client's locale |
| * @return message String |
| */ |
| protected String stop(ContextName cn, StringManager smClient) { |
| |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| super.stop(printWriter, cn, smClient); |
| |
| return stringWriter.toString(); |
| } |
| |
| /** |
| * Find potential memory leaks caused by web application reload. |
| * |
| * @see ManagerServlet#findleaks(boolean, PrintWriter, StringManager) |
| * |
| * @param smClient StringManager for the client's locale |
| * |
| * @return message String |
| */ |
| protected String findleaks(StringManager smClient) { |
| |
| StringBuilder msg = new StringBuilder(); |
| |
| StringWriter stringWriter = new StringWriter(); |
| PrintWriter printWriter = new PrintWriter(stringWriter); |
| |
| super.findleaks(false, printWriter, smClient); |
| |
| String writerText = stringWriter.toString(); |
| |
| if (writerText.length() > 0) { |
| if (!writerText.startsWith("FAIL -")) { |
| msg.append(smClient.getString( |
| "htmlManagerServlet.findleaksList")); |
| } |
| msg.append(writerText); |
| } else { |
| msg.append(smClient.getString("htmlManagerServlet.findleaksNone")); |
| } |
| |
| return msg.toString(); |
| } |
| |
| |
| protected void sslConnectorCiphers(HttpServletRequest request, |
| HttpServletResponse response) throws ServletException, IOException { |
| request.setAttribute("cipherList", getConnectorCiphers()); |
| getServletContext().getRequestDispatcher( |
| connectorCiphersJspPath).forward(request, response); |
| } |
| |
| /** |
| * @see javax.servlet.Servlet#getServletInfo() |
| */ |
| @Override |
| public String getServletInfo() { |
| return "HTMLManagerServlet, Copyright (c) 1999-2016, The Apache Software Foundation"; |
| } |
| |
| /** |
| * @see javax.servlet.GenericServlet#init() |
| */ |
| @Override |
| public void init() throws ServletException { |
| super.init(); |
| |
| // Set our properties from the initialization parameters |
| String value = null; |
| value = getServletConfig().getInitParameter("showProxySessions"); |
| showProxySessions = Boolean.parseBoolean(value); |
| } |
| |
| // ------------------------------------------------ Sessions administration |
| |
| /** |
| * |
| * Extract the expiration request parameter |
| * |
| * @param cn Name of the application from which to expire sessions |
| * @param req The Servlet request |
| * @param smClient StringManager for the client's locale |
| * @return message string |
| */ |
| protected String expireSessions(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("Could not parse idle parameter to an int: " + idleParam); |
| } |
| } |
| return sessions(cn, idle, smClient); |
| } |
| |
| /** |
| * Handle session operations. |
| * |
| * @param cn Name of the application for the sessions operation |
| * @param req The Servlet request |
| * @param resp The Servlet response |
| * @param smClient StringManager for the client's locale |
| * @throws ServletException Propagated Servlet error |
| * @throws IOException An IO error occurred |
| */ |
| protected void doSessions(ContextName cn, HttpServletRequest req, |
| HttpServletResponse resp, StringManager smClient) |
| throws ServletException, IOException { |
| req.setAttribute("path", cn.getPath()); |
| req.setAttribute("version", cn.getVersion()); |
| String action = req.getParameter("action"); |
| if (debug >= 1) { |
| log("sessions: Session action '" + action + |
| "' for web application '" + cn.getDisplayName() + "'"); |
| } |
| if ("sessionDetail".equals(action)) { |
| String sessionId = req.getParameter("sessionId"); |
| displaySessionDetailPage(req, resp, cn, sessionId, smClient); |
| return; |
| } else if ("invalidateSessions".equals(action)) { |
| String[] sessionIds = req.getParameterValues("sessionIds"); |
| int i = invalidateSessions(cn, sessionIds, smClient); |
| req.setAttribute(APPLICATION_MESSAGE, "" + i + " sessions invalidated."); |
| } else if ("removeSessionAttribute".equals(action)) { |
| String sessionId = req.getParameter("sessionId"); |
| String name = req.getParameter("attributeName"); |
| boolean removed = |
| removeSessionAttribute(cn, sessionId, name, smClient); |
| String outMessage = removed ? "Session attribute '" + name + "' removed." : "Session did not contain any attribute named '" + name + "'"; |
| req.setAttribute(APPLICATION_MESSAGE, outMessage); |
| displaySessionDetailPage(req, resp, cn, sessionId, smClient); |
| return; |
| } // else |
| displaySessionsListPage(cn, req, resp, smClient); |
| } |
| |
| protected List<Session> getSessionsForName(ContextName cn, |
| StringManager smClient) { |
| if ((cn == null) || !(cn.getPath().startsWith("/") || |
| cn.getPath().equals(""))) { |
| String path = null; |
| if (cn != null) { |
| path = cn.getPath(); |
| } |
| throw new IllegalArgumentException(smClient.getString( |
| "managerServlet.invalidPath", |
| RequestUtil.filter(path))); |
| } |
| |
| Context ctxt = (Context) host.findChild(cn.getName()); |
| if (null == ctxt) { |
| throw new IllegalArgumentException(smClient.getString( |
| "managerServlet.noContext", |
| RequestUtil.filter(cn.getDisplayName()))); |
| } |
| Manager manager = ctxt.getManager(); |
| List<Session> sessions = new ArrayList<>(); |
| sessions.addAll(Arrays.asList(manager.findSessions())); |
| if (manager instanceof DistributedManager && showProxySessions) { |
| // Add dummy proxy sessions |
| Set<String> sessionIds = |
| ((DistributedManager) manager).getSessionIdsFull(); |
| // Remove active (primary and backup) session IDs from full list |
| for (Session session : sessions) { |
| sessionIds.remove(session.getId()); |
| } |
| // Left with just proxy sessions - add them |
| for (String sessionId : sessionIds) { |
| sessions.add(new DummyProxySession(sessionId)); |
| } |
| } |
| return sessions; |
| } |
| |
| protected Session getSessionForNameAndId(ContextName cn, String id, |
| StringManager smClient) { |
| |
| List<Session> sessions = getSessionsForName(cn, smClient); |
| if (sessions.isEmpty()) return null; |
| for(Session session : sessions) { |
| if (session.getId().equals(id)) { |
| return session; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * List session. |
| * @param cn Name of the application for which the sessions will be listed |
| * @param req The Servlet request |
| * @param resp The Servlet response |
| * @param smClient StringManager for the client's locale |
| * @throws ServletException Propagated Servlet error |
| * @throws IOException An IO error occurred |
| */ |
| protected void displaySessionsListPage(ContextName cn, |
| HttpServletRequest req, HttpServletResponse resp, |
| StringManager smClient) |
| throws ServletException, IOException { |
| List<Session> sessions = getSessionsForName(cn, smClient); |
| String sortBy = req.getParameter("sort"); |
| String orderBy = null; |
| if (null != sortBy && !"".equals(sortBy.trim())) { |
| Comparator<Session> comparator = getComparator(sortBy); |
| if (comparator != null) { |
| orderBy = req.getParameter("order"); |
| if ("DESC".equalsIgnoreCase(orderBy)) { |
| comparator = Collections.reverseOrder(comparator); |
| orderBy = "ASC"; |
| } else { |
| orderBy = "DESC"; |
| } |
| try { |
| Collections.sort(sessions, comparator); |
| } catch (IllegalStateException ise) { |
| // at least 1 of the sessions is invalidated |
| req.setAttribute(APPLICATION_ERROR, "Can't sort session list: one session is invalidated"); |
| } |
| } else { |
| log("WARNING: unknown sort order: " + sortBy); |
| } |
| } |
| // keep sort order |
| req.setAttribute("sort", sortBy); |
| req.setAttribute("order", orderBy); |
| req.setAttribute("activeSessions", sessions); |
| //strong>NOTE</strong> - This header will be overridden |
| // automatically if a <code>RequestDispatcher.forward()</code> call is |
| // ultimately invoked. |
| resp.setHeader("Pragma", "No-cache"); // HTTP 1.0 |
| resp.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); // HTTP 1.1 |
| resp.setDateHeader("Expires", 0); // 0 means now |
| getServletContext().getRequestDispatcher(sessionsListJspPath).include(req, resp); |
| } |
| |
| /** |
| * Display session details. |
| * |
| * @param req The Servlet request |
| * @param resp The Servlet response |
| * @param cn Name of the application for which the sessions will be listed |
| * @param sessionId the session id |
| * @param smClient StringManager for the client's locale |
| * @throws ServletException Propagated Servlet error |
| * @throws IOException An IO error occurred |
| */ |
| protected void displaySessionDetailPage(HttpServletRequest req, |
| HttpServletResponse resp, ContextName cn, String sessionId, |
| StringManager smClient) throws ServletException, IOException { |
| Session session = getSessionForNameAndId(cn, sessionId, smClient); |
| //strong>NOTE</strong> - This header will be overridden |
| // automatically if a <code>RequestDispatcher.forward()</code> call is |
| // ultimately invoked. |
| resp.setHeader("Pragma", "No-cache"); // HTTP 1.0 |
| resp.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); // HTTP 1.1 |
| resp.setDateHeader("Expires", 0); // 0 means now |
| req.setAttribute("currentSession", session); |
| getServletContext().getRequestDispatcher(resp.encodeURL(sessionDetailJspPath)).include(req, resp); |
| } |
| |
| /** |
| * Invalidate specified sessions. |
| * |
| * @param cn Name of the application for which sessions are to be |
| * invalidated |
| * @param sessionIds the session ids of the sessions |
| * @param smClient StringManager for the client's locale |
| * @return number of invalidated sessions |
| */ |
| protected int invalidateSessions(ContextName cn, String[] sessionIds, |
| StringManager smClient) { |
| if (null == sessionIds) { |
| return 0; |
| } |
| int nbAffectedSessions = 0; |
| for (int i = 0; i < sessionIds.length; ++i) { |
| String sessionId = sessionIds[i]; |
| HttpSession session = |
| getSessionForNameAndId(cn, sessionId, smClient).getSession(); |
| if (null == session) { |
| // Shouldn't happen, but let's play nice... |
| if (debug >= 1) { |
| log("WARNING: can't invalidate null session " + sessionId); |
| } |
| continue; |
| } |
| try { |
| session.invalidate(); |
| ++nbAffectedSessions; |
| if (debug >= 1) { |
| log("Invalidating session id " + sessionId); |
| } |
| } catch (IllegalStateException ise) { |
| if (debug >= 1) { |
| log("Can't invalidate already invalidated session id " + sessionId); |
| } |
| } |
| } |
| return nbAffectedSessions; |
| } |
| |
| /** |
| * Removes an attribute from an HttpSession |
| * @param cn Name of the application hosting the session from which the |
| * attribute is to be removed |
| * @param sessionId the session id |
| * @param attributeName the attribute name |
| * @param smClient StringManager for the client's locale |
| * @return true if there was an attribute removed, false otherwise |
| */ |
| protected boolean removeSessionAttribute(ContextName cn, String sessionId, |
| String attributeName, StringManager smClient) { |
| HttpSession session = |
| getSessionForNameAndId(cn, sessionId, smClient).getSession(); |
| if (null == session) { |
| // Shouldn't happen, but let's play nice... |
| if (debug >= 1) { |
| log("WARNING: can't remove attribute '" + attributeName + "' for null session " + sessionId); |
| } |
| return false; |
| } |
| boolean wasPresent = (null != session.getAttribute(attributeName)); |
| try { |
| session.removeAttribute(attributeName); |
| } catch (IllegalStateException ise) { |
| if (debug >= 1) { |
| log("Can't remote attribute '" + attributeName + "' for invalidated session id " + sessionId); |
| } |
| } |
| return wasPresent; |
| } |
| |
| protected Comparator<Session> getComparator(String sortBy) { |
| Comparator<Session> comparator = null; |
| if ("CreationTime".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<Date>() { |
| @Override |
| public Comparable<Date> getComparableObject(Session session) { |
| return new Date(session.getCreationTime()); |
| } |
| }; |
| } else if ("id".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<String>() { |
| @Override |
| public Comparable<String> getComparableObject(Session session) { |
| return session.getId(); |
| } |
| }; |
| } else if ("LastAccessedTime".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<Date>() { |
| @Override |
| public Comparable<Date> getComparableObject(Session session) { |
| return new Date(session.getLastAccessedTime()); |
| } |
| }; |
| } else if ("MaxInactiveInterval".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<Integer>() { |
| @Override |
| public Comparable<Integer> getComparableObject(Session session) { |
| return Integer.valueOf(session.getMaxInactiveInterval()); |
| } |
| }; |
| } else if ("new".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<Boolean>() { |
| @Override |
| public Comparable<Boolean> getComparableObject(Session session) { |
| return Boolean.valueOf(session.getSession().isNew()); |
| } |
| }; |
| } else if ("locale".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<String>() { |
| @Override |
| public Comparable<String> getComparableObject(Session session) { |
| return JspHelper.guessDisplayLocaleFromSession(session); |
| } |
| }; |
| } else if ("user".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<String>() { |
| @Override |
| public Comparable<String> getComparableObject(Session session) { |
| return JspHelper.guessDisplayUserFromSession(session); |
| } |
| }; |
| } else if ("UsedTime".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<Date>() { |
| @Override |
| public Comparable<Date> getComparableObject(Session session) { |
| return new Date(SessionUtils.getUsedTimeForSession(session)); |
| } |
| }; |
| } else if ("InactiveTime".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<Date>() { |
| @Override |
| public Comparable<Date> getComparableObject(Session session) { |
| return new Date(SessionUtils.getInactiveTimeForSession(session)); |
| } |
| }; |
| } else if ("TTL".equalsIgnoreCase(sortBy)) { |
| comparator = new BaseSessionComparator<Date>() { |
| @Override |
| public Comparable<Date> getComparableObject(Session session) { |
| return new Date(SessionUtils.getTTLForSession(session)); |
| } |
| }; |
| } |
| return comparator; |
| } |
| |
| // ------------------------------------------------------ Private Constants |
| |
| // These HTML sections are broken in relatively small sections, because of |
| // limited number of substitutions MessageFormat can process |
| // (maximum of 10). |
| |
| private static final String APPS_HEADER_SECTION = |
| "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n" + |
| "<tr>\n" + |
| " <td colspan=\"6\" class=\"title\">{0}</td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td class=\"header-left\"><small>{1}</small></td>\n" + |
| " <td class=\"header-left\"><small>{2}</small></td>\n" + |
| " <td class=\"header-center\"><small>{3}</small></td>\n" + |
| " <td class=\"header-center\"><small>{4}</small></td>\n" + |
| " <td class=\"header-left\"><small>{5}</small></td>\n" + |
| " <td class=\"header-left\"><small>{6}</small></td>\n" + |
| "</tr>\n"; |
| |
| private static final String APPS_ROW_DETAILS_SECTION = |
| "<tr>\n" + |
| " <td class=\"row-left\" bgcolor=\"{6}\" rowspan=\"2\"><small>{0}</small></td>\n" + |
| " <td class=\"row-left\" bgcolor=\"{6}\" rowspan=\"2\"><small>{1}</small></td>\n" + |
| " <td class=\"row-left\" bgcolor=\"{6}\" rowspan=\"2\"><small>{2}</small></td>\n" + |
| " <td class=\"row-center\" bgcolor=\"{6}\" rowspan=\"2\"><small>{3}</small></td>\n" + |
| " <td class=\"row-center\" bgcolor=\"{6}\" rowspan=\"2\">" + |
| "<small><a href=\"{4}\">{5}</a></small></td>\n"; |
| |
| private static final String MANAGER_APP_ROW_BUTTON_SECTION = |
| " <td class=\"row-left\" bgcolor=\"{13}\">\n" + |
| " <small>\n" + |
| " {1} \n" + |
| " {3} \n" + |
| " {5} \n" + |
| " {7} \n" + |
| " </small>\n" + |
| " </td>\n" + |
| "</tr><tr>\n" + |
| " <td class=\"row-left\" bgcolor=\"{13}\">\n" + |
| " <form method=\"POST\" action=\"{8}\">\n" + |
| " <small>\n" + |
| " <input type=\"submit\" value=\"{9}\"> {10} <input type=\"text\" name=\"idle\" size=\"5\" value=\"{11}\"> {12} \n" + |
| " </small>\n" + |
| " </form>\n" + |
| " </td>\n" + |
| "</tr>\n"; |
| |
| private static final String STARTED_DEPLOYED_APPS_ROW_BUTTON_SECTION = |
| " <td class=\"row-left\" bgcolor=\"{13}\">\n" + |
| " <small>{1}</small> \n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{2}\">" + |
| " <small><input type=\"submit\" value=\"{3}\"></small>" + |
| " </form>\n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{4}\">" + |
| " <small><input type=\"submit\" value=\"{5}\"></small>" + |
| " </form>\n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{6}\">" + |
| " <small><input type=\"submit\" value=\"{7}\"></small>" + |
| " </form>\n" + |
| " </td>\n" + |
| " </tr><tr>\n" + |
| " <td class=\"row-left\" bgcolor=\"{13}\">\n" + |
| " <form method=\"POST\" action=\"{8}\">\n" + |
| " <small>\n" + |
| " <input type=\"submit\" value=\"{9}\"> {10} <input type=\"text\" name=\"idle\" size=\"5\" value=\"{11}\"> {12} \n" + |
| " </small>\n" + |
| " </form>\n" + |
| " </td>\n" + |
| "</tr>\n"; |
| |
| private static final String STOPPED_DEPLOYED_APPS_ROW_BUTTON_SECTION = |
| " <td class=\"row-left\" bgcolor=\"{13}\" rowspan=\"2\">\n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{0}\">" + |
| " <small><input type=\"submit\" value=\"{1}\"></small>" + |
| " </form>\n" + |
| " <small>{3}</small> \n" + |
| " <small>{5}</small> \n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{6}\">" + |
| " <small><input type=\"submit\" value=\"{7}\"></small>" + |
| " </form>\n" + |
| " </td>\n" + |
| "</tr>\n<tr></tr>\n"; |
| |
| private static final String STARTED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION = |
| " <td class=\"row-left\" bgcolor=\"{13}\">\n" + |
| " <small>{1}</small> \n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{2}\">" + |
| " <small><input type=\"submit\" value=\"{3}\"></small>" + |
| " </form>\n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{4}\">" + |
| " <small><input type=\"submit\" value=\"{5}\"></small>" + |
| " </form>\n" + |
| " <small>{7}</small> \n" + |
| " </td>\n" + |
| " </tr><tr>\n" + |
| " <td class=\"row-left\" bgcolor=\"{13}\">\n" + |
| " <form method=\"POST\" action=\"{8}\">\n" + |
| " <small>\n" + |
| " <input type=\"submit\" value=\"{9}\"> {10} <input type=\"text\" name=\"idle\" size=\"5\" value=\"{11}\"> {12} \n" + |
| " </small>\n" + |
| " </form>\n" + |
| " </td>\n" + |
| "</tr>\n"; |
| |
| private static final String STOPPED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION = |
| " <td class=\"row-left\" bgcolor=\"{13}\" rowspan=\"2\">\n" + |
| " <form class=\"inline\" method=\"POST\" action=\"{0}\">" + |
| " <small><input type=\"submit\" value=\"{1}\"></small>" + |
| " </form>\n" + |
| " <small>{3}</small> \n" + |
| " <small>{5}</small> \n" + |
| " <small>{7}</small> \n" + |
| " </td>\n" + |
| "</tr>\n<tr></tr>\n"; |
| |
| private static final String DEPLOY_SECTION = |
| "</table>\n" + |
| "<br>\n" + |
| "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\" class=\"title\">{0}</td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\" class=\"header-left\"><small>{1}</small></td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\">\n" + |
| "<form method=\"post\" action=\"{2}\">\n" + |
| "<table cellspacing=\"0\" cellpadding=\"3\">\n" + |
| "<tr>\n" + |
| " <td class=\"row-right\">\n" + |
| " <small>{3}</small>\n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"text\" name=\"deployPath\" size=\"20\">\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td class=\"row-right\">\n" + |
| " <small>{4}</small>\n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"text\" name=\"deployConfig\" size=\"20\">\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td class=\"row-right\">\n" + |
| " <small>{5}</small>\n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"text\" name=\"deployWar\" size=\"40\">\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td class=\"row-right\">\n" + |
| " \n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"submit\" value=\"{6}\">\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "</table>\n" + |
| "</form>\n" + |
| "</td>\n" + |
| "</tr>\n"; |
| |
| private static final String UPLOAD_SECTION = |
| "<tr>\n" + |
| " <td colspan=\"2\" class=\"header-left\"><small>{0}</small></td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\">\n" + |
| "<form method=\"post\" action=\"{1}\" " + |
| "enctype=\"multipart/form-data\">\n" + |
| "<table cellspacing=\"0\" cellpadding=\"3\">\n" + |
| "<tr>\n" + |
| " <td class=\"row-right\">\n" + |
| " <small>{2}</small>\n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"file\" name=\"deployWar\" size=\"40\">\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td class=\"row-right\">\n" + |
| " \n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"submit\" value=\"{3}\">\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "</table>\n" + |
| "</form>\n" + |
| "</td>\n" + |
| "</tr>\n" + |
| "</table>\n" + |
| "<br>\n" + |
| "\n"; |
| |
| private static final String DIAGNOSTICS_SECTION = |
| "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\" class=\"title\">{0}</td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\" class=\"header-left\"><small>{1}</small></td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\">\n" + |
| "<form method=\"post\" action=\"{2}\">\n" + |
| "<table cellspacing=\"0\" cellpadding=\"3\">\n" + |
| "<tr>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"submit\" value=\"{4}\">\n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <small>{3}</small>\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "</table>\n" + |
| "</form>\n" + |
| "</td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\" class=\"header-left\"><small>{5}</small></td>\n" + |
| "</tr>\n" + |
| "<tr>\n" + |
| " <td colspan=\"2\">\n" + |
| "<form method=\"post\" action=\"{6}\">\n" + |
| "<table cellspacing=\"0\" cellpadding=\"3\">\n" + |
| "<tr>\n" + |
| " <td class=\"row-left\">\n" + |
| " <input type=\"submit\" value=\"{7}\">\n" + |
| " </td>\n" + |
| " <td class=\"row-left\">\n" + |
| " <small>{8}</small>\n" + |
| " </td>\n" + |
| "</tr>\n" + |
| "</table>\n" + |
| "</form>\n" + |
| "</td>\n" + |
| "</tr>\n" + |
| "</table>\n" + |
| "<br>"; |
| } |