001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.catalina.manager.host;
019:
020: import java.io.IOException;
021: import java.io.PrintWriter;
022: import java.io.StringWriter;
023: import java.text.MessageFormat;
024: import java.util.Iterator;
025: import java.util.Map;
026: import java.util.TreeMap;
027:
028: import javax.servlet.ServletException;
029: import javax.servlet.http.HttpServletRequest;
030: import javax.servlet.http.HttpServletResponse;
031:
032: import org.apache.catalina.Container;
033: import org.apache.catalina.Host;
034: import org.apache.catalina.util.RequestUtil;
035: import org.apache.catalina.util.ServerInfo;
036:
037: /**
038: * Servlet that enables remote management of the virtual hosts deployed
039: * on the server. Normally, this functionality will be protected by a security
040: * constraint in the web application deployment descriptor. However,
041: * this requirement can be relaxed during testing.
042: * <p>
043: * The difference between the <code>HostManagerServlet</code> and this
044: * Servlet is that this Servlet prints out a HTML interface which
045: * makes it easier to administrate.
046: * <p>
047: * However if you use a software that parses the output of
048: * <code>HostManagerServlet</code> you won't be able to upgrade
049: * to this Servlet since the output are not in the
050: * same format as from <code>HostManagerServlet</code>
051: *
052: * @author Bip Thelin
053: * @author Malcolm Edgar
054: * @author Glenn L. Nielsen
055: * @author Peter Rossbach
056: * @version $Revision: 557454 $, $Date: 2007-07-19 04:19:10 +0200 (jeu., 19 juil. 2007) $
057: * @see ManagerServlet
058: */
059:
060: public final class HTMLHostManagerServlet extends HostManagerServlet {
061:
062: // --------------------------------------------------------- Public Methods
063:
064: /**
065: * Process a GET request for the specified resource.
066: *
067: * @param request The servlet request we are processing
068: * @param response The servlet response we are creating
069: *
070: * @exception IOException if an input/output error occurs
071: * @exception ServletException if a servlet-specified error occurs
072: */
073: public void doGet(HttpServletRequest request,
074: HttpServletResponse response) throws IOException,
075: ServletException {
076:
077: // Identify the request parameters that we need
078: String command = request.getPathInfo();
079:
080: String name = request.getParameter("name");
081:
082: // Prepare our output writer to generate the response message
083: response.setContentType("text/html; charset="
084: + Constants.CHARSET);
085:
086: String message = "";
087: // Process the requested command
088: if (command == null) {
089: } else if (command.equals("/add")) {
090: message = add(request, name);
091: } else if (command.equals("/remove")) {
092: message = remove(name);
093: } else if (command.equals("/list")) {
094: } else if (command.equals("/start")) {
095: message = start(name);
096: } else if (command.equals("/stop")) {
097: message = stop(name);
098: } else {
099: message = sm.getString("hostManagerServlet.unknownCommand",
100: command);
101: }
102:
103: list(request, response, message);
104: }
105:
106: /**
107: * Add a host using the specified parameters.
108: *
109: * @param name host name
110: */
111: protected String add(HttpServletRequest request, String name) {
112:
113: StringWriter stringWriter = new StringWriter();
114: PrintWriter printWriter = new PrintWriter(stringWriter);
115:
116: super .add(request, printWriter, name, true);
117:
118: return stringWriter.toString();
119: }
120:
121: /**
122: * Remove the specified host.
123: *
124: * @param writer Writer to render results to
125: * @param name host name
126: */
127: protected String remove(String name) {
128:
129: StringWriter stringWriter = new StringWriter();
130: PrintWriter printWriter = new PrintWriter(stringWriter);
131:
132: super .remove(printWriter, name);
133:
134: return stringWriter.toString();
135: }
136:
137: /**
138: * Start the host with the specified name.
139: *
140: * @param name Host name
141: */
142: protected String start(String name) {
143:
144: StringWriter stringWriter = new StringWriter();
145: PrintWriter printWriter = new PrintWriter(stringWriter);
146:
147: super .start(printWriter, name);
148:
149: return stringWriter.toString();
150: }
151:
152: /**
153: * Stop the host with the specified name.
154: *
155: * @param name Host name
156: */
157: protected String stop(String name) {
158:
159: StringWriter stringWriter = new StringWriter();
160: PrintWriter printWriter = new PrintWriter(stringWriter);
161:
162: super .stop(printWriter, name);
163:
164: return stringWriter.toString();
165: }
166:
167: /**
168: * Render a HTML list of the currently active Contexts in our virtual host,
169: * and memory and server status information.
170: *
171: * @param request The request
172: * @param response The response
173: * @param message a message to display
174: */
175: public void list(HttpServletRequest request,
176: HttpServletResponse response, String message)
177: throws IOException {
178:
179: PrintWriter writer = response.getWriter();
180:
181: // HTML Header Section
182: writer.print(Constants.HTML_HEADER_SECTION);
183:
184: // Body Header Section
185: Object[] args = new Object[2];
186: args[0] = request.getContextPath();
187: args[1] = sm.getString("htmlHostManagerServlet.title");
188: writer.print(MessageFormat.format(
189: Constants.BODY_HEADER_SECTION, args));
190:
191: // Message Section
192: args = new Object[3];
193: args[0] = sm.getString("htmlHostManagerServlet.messageLabel");
194: if (message == null || message.length() == 0) {
195: args[1] = "OK";
196: } else {
197: args[1] = RequestUtil.filter(message);
198: }
199: writer.print(MessageFormat.format(Constants.MESSAGE_SECTION,
200: args));
201:
202: // Manager Section
203: args = new Object[9];
204: args[0] = sm.getString("htmlHostManagerServlet.manager");
205: args[1] = response.encodeURL(request.getContextPath()
206: + "/html/list");
207: args[2] = sm.getString("htmlHostManagerServlet.list");
208: args[3] = response
209: .encodeURL(request.getContextPath()
210: + "/"
211: + sm
212: .getString("htmlHostManagerServlet.helpHtmlManagerFile"));
213: args[4] = sm
214: .getString("htmlHostManagerServlet.helpHtmlManager");
215: args[5] = response
216: .encodeURL(request.getContextPath()
217: + "/"
218: + sm
219: .getString("htmlHostManagerServlet.helpManagerFile"));
220: args[6] = sm.getString("htmlHostManagerServlet.helpManager");
221: args[7] = response.encodeURL("/manager/status");
222: args[8] = sm.getString("statusServlet.title");
223: writer.print(MessageFormat.format(Constants.MANAGER_SECTION,
224: args));
225:
226: // Hosts Header Section
227: args = new Object[3];
228: args[0] = sm.getString("htmlHostManagerServlet.hostName");
229: args[1] = sm.getString("htmlHostManagerServlet.hostAliases");
230: args[2] = sm.getString("htmlHostManagerServlet.hostTasks");
231: writer.print(MessageFormat.format(HOSTS_HEADER_SECTION, args));
232:
233: // Hosts Row Section
234: // Create sorted map of host names.
235: Container[] children = engine.findChildren();
236: String hostNames[] = new String[children.length];
237: for (int i = 0; i < children.length; i++)
238: hostNames[i] = children[i].getName();
239:
240: TreeMap<String, String> sortedHostNamesMap = new TreeMap<String, String>();
241:
242: for (int i = 0; i < hostNames.length; i++) {
243: String displayPath = hostNames[i];
244: sortedHostNamesMap.put(displayPath, hostNames[i]);
245: }
246:
247: String hostsStart = sm
248: .getString("htmlHostManagerServlet.hostsStart");
249: String hostsStop = sm
250: .getString("htmlHostManagerServlet.hostsStop");
251: String hostsRemove = sm
252: .getString("htmlHostManagerServlet.hostsRemove");
253:
254: Iterator<Map.Entry<String, String>> iterator = sortedHostNamesMap
255: .entrySet().iterator();
256: while (iterator.hasNext()) {
257: Map.Entry<String, String> entry = iterator.next();
258: String hostName = (String) entry.getKey();
259: Host host = (Host) engine.findChild(hostName);
260:
261: if (host != null) {
262: args = new Object[2];
263: args[0] = RequestUtil.filter(hostName);
264: String[] aliases = host.findAliases();
265: StringBuffer buf = new StringBuffer();
266: if (aliases.length > 0) {
267: buf.append(aliases[0]);
268: for (int j = 1; j < aliases.length; j++) {
269: buf.append(", ").append(aliases[j]);
270: }
271: }
272:
273: if (buf.length() == 0) {
274: buf.append(" ");
275: args[1] = buf.toString();
276: } else {
277: args[1] = RequestUtil.filter(buf.toString());
278: }
279:
280: writer.print(MessageFormat.format(
281: HOSTS_ROW_DETAILS_SECTION, args));
282:
283: args = new Object[7];
284: args[0] = response.encodeURL(request.getContextPath()
285: + "/html/start?name=" + hostName);
286: args[1] = hostsStart;
287: args[2] = response.encodeURL(request.getContextPath()
288: + "/html/stop?name=" + hostName);
289: args[3] = hostsStop;
290: args[4] = response.encodeURL(request.getContextPath()
291: + "/html/remove?name=" + hostName);
292: args[5] = hostsRemove;
293: args[6] = hostName;
294: if (host == this .host) {
295: writer.print(MessageFormat.format(
296: MANAGER_HOST_ROW_BUTTON_SECTION, args));
297: } else {
298: writer.print(MessageFormat.format(
299: HOSTS_ROW_BUTTON_SECTION, args));
300: }
301:
302: }
303: }
304:
305: // Add Section
306: args = new Object[6];
307: args[0] = sm.getString("htmlHostManagerServlet.addTitle");
308: args[1] = sm.getString("htmlHostManagerServlet.addHost");
309: args[2] = response.encodeURL(request.getContextPath()
310: + "/html/add");
311: args[3] = sm.getString("htmlHostManagerServlet.addName");
312: args[4] = sm.getString("htmlHostManagerServlet.addAliases");
313: args[5] = sm.getString("htmlHostManagerServlet.addAppBase");
314: writer.print(MessageFormat.format(ADD_SECTION_START, args));
315:
316: args = new Object[3];
317: args[0] = sm.getString("htmlHostManagerServlet.addAutoDeploy");
318: args[1] = "autoDeploy";
319: args[2] = "checked";
320: writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
321: args[0] = sm
322: .getString("htmlHostManagerServlet.addDeployOnStartup");
323: args[1] = "deployOnStartup";
324: args[2] = "checked";
325: writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
326: args[0] = sm.getString("htmlHostManagerServlet.addDeployXML");
327: args[1] = "deployXML";
328: args[2] = "checked";
329: writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
330: args[0] = sm.getString("htmlHostManagerServlet.addUnpackWARs");
331: args[1] = "unpackWARs";
332: args[2] = "checked";
333: writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
334: args[0] = sm
335: .getString("htmlHostManagerServlet.addXmlNamespaceAware");
336: args[1] = "xmlNamespaceAware";
337: args[2] = "";
338: writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
339: args[0] = sm
340: .getString("htmlHostManagerServlet.addXmlValidation");
341: args[1] = "xmlValidation";
342: args[2] = "";
343: writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
344:
345: args[0] = sm.getString("htmlHostManagerServlet.addManager");
346: args[1] = "manager";
347: args[2] = "checked";
348: writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
349:
350: args = new Object[1];
351: args[0] = sm.getString("htmlHostManagerServlet.addButton");
352: writer.print(MessageFormat.format(ADD_SECTION_END, args));
353:
354: // Server Header Section
355: args = new Object[7];
356: args[0] = sm.getString("htmlHostManagerServlet.serverTitle");
357: args[1] = sm.getString("htmlHostManagerServlet.serverVersion");
358: args[2] = sm
359: .getString("htmlHostManagerServlet.serverJVMVersion");
360: args[3] = sm
361: .getString("htmlHostManagerServlet.serverJVMVendor");
362: args[4] = sm.getString("htmlHostManagerServlet.serverOSName");
363: args[5] = sm
364: .getString("htmlHostManagerServlet.serverOSVersion");
365: args[6] = sm.getString("htmlHostManagerServlet.serverOSArch");
366: writer.print(MessageFormat.format(
367: Constants.SERVER_HEADER_SECTION, args));
368:
369: // Server Row Section
370: args = new Object[6];
371: args[0] = ServerInfo.getServerInfo();
372: args[1] = System.getProperty("java.runtime.version");
373: args[2] = System.getProperty("java.vm.vendor");
374: args[3] = System.getProperty("os.name");
375: args[4] = System.getProperty("os.version");
376: args[5] = System.getProperty("os.arch");
377: writer.print(MessageFormat.format(Constants.SERVER_ROW_SECTION,
378: args));
379:
380: // HTML Tail Section
381: writer.print(Constants.HTML_TAIL_SECTION);
382:
383: // Finish up the response
384: writer.flush();
385: writer.close();
386: }
387:
388: // ------------------------------------------------------ Private Constants
389:
390: // These HTML sections are broken in relatively small sections, because of
391: // limited number of subsitutions MessageFormat can process
392: // (maximium of 10).
393:
394: private static final String HOSTS_HEADER_SECTION = "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n"
395: + "<tr>\n"
396: + " <td colspan=\"5\" class=\"title\">{0}</td>\n"
397: + "</tr>\n"
398: + "<tr>\n"
399: + " <td class=\"header-left\"><small>{0}</small></td>\n"
400: + " <td class=\"header-center\"><small>{1}</small></td>\n"
401: + " <td class=\"header-center\"><small>{2}</small></td>\n"
402: + "</tr>\n";
403:
404: private static final String HOSTS_ROW_DETAILS_SECTION = "<tr>\n"
405: + " <td class=\"row-left\"><small><a href=\"http://{0}\">{0}</a>"
406: + "</small></td>\n"
407: + " <td class=\"row-center\"><small>{1}</small></td>\n";
408:
409: private static final String MANAGER_HOST_ROW_BUTTON_SECTION = " <td class=\"row-left\">\n"
410: + " <small>\n"
411: + " {1} \n"
412: + " {3} \n"
413: + " {5} \n"
414: + " </small>\n" + " </td>\n" + "</tr>\n";
415:
416: private static final String HOSTS_ROW_BUTTON_SECTION = " <td class=\"row-left\" NOWRAP>\n"
417: + " <small>\n"
418: + " <a href=\"{0}\" onclick=\"return(confirm(''{1} {6}\\n\\nAre you sure?''))\">{1}</a> \n"
419: + " <a href=\"{2}\" onclick=\"return(confirm(''{3} {6}\\n\\nAre you sure?''))\">{3}</a> \n"
420: + " <a href=\"{4}\" onclick=\"return(confirm(''{5} {6}\\n\\nAre you sure?''))\">{5}</a> \n"
421: + " </small>\n" + " </td>\n" + "</tr>\n";
422:
423: private static final String ADD_SECTION_START = "</table>\n"
424: + "<br>\n"
425: + "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n"
426: + "<tr>\n"
427: + " <td colspan=\"2\" class=\"title\">{0}</td>\n"
428: + "</tr>\n"
429: + "<tr>\n"
430: + " <td colspan=\"2\" class=\"header-left\"><small>{1}</small></td>\n"
431: + "</tr>\n" + "<tr>\n" + " <td colspan=\"2\">\n"
432: + "<form method=\"get\" action=\"{2}\">\n"
433: + "<table cellspacing=\"0\" cellpadding=\"3\">\n"
434: + "<tr>\n" + " <td class=\"row-right\">\n"
435: + " <small>{3}</small>\n" + " </td>\n"
436: + " <td class=\"row-left\">\n"
437: + " <input type=\"text\" name=\"name\" size=\"20\">\n"
438: + " </td>\n" + "</tr>\n" + "<tr>\n"
439: + " <td class=\"row-right\">\n" + " <small>{4}</small>\n"
440: + " </td>\n" + " <td class=\"row-left\">\n"
441: + " <input type=\"text\" name=\"aliases\" size=\"64\">\n"
442: + " </td>\n" + "</tr>\n" + "<tr>\n"
443: + " <td class=\"row-right\">\n" + " <small>{5}</small>\n"
444: + " </td>\n" + " <td class=\"row-left\">\n"
445: + " <input type=\"text\" name=\"appBase\" size=\"64\">\n"
446: + " </td>\n" + "</tr>\n";
447:
448: private static final String ADD_SECTION_BOOLEAN = "<tr>\n"
449: + " <td class=\"row-right\">\n" + " <small>{0}</small>\n"
450: + " </td>\n" + " <td class=\"row-left\">\n"
451: + " <input type=\"checkbox\" name=\"{1}\" {2}>\n"
452: + " </td>\n" + "</tr>\n";
453:
454: private static final String ADD_SECTION_END = "<tr>\n"
455: + " <td class=\"row-right\">\n" + " \n" + " </td>\n"
456: + " <td class=\"row-left\">\n"
457: + " <input type=\"submit\" value=\"{0}\">\n" + " </td>\n"
458: + "</tr>\n" + "</table>\n" + "</form>\n" + "</td>\n"
459: + "</tr>\n" + "</table>\n" + "<br>\n" + "\n";
460:
461: }
|