View Javadoc

1   /*
2    * Copyright 1999,2004-2005 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  
18  package org.apache.catalina.manager;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.PrintWriter;
23  import java.io.StringWriter;
24  import java.text.MessageFormat;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.TreeMap;
29  import javax.servlet.ServletException;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.apache.catalina.Container;
34  import org.apache.catalina.Context;
35  import org.apache.catalina.util.RequestUtil;
36  import org.apache.catalina.Host;
37  import org.apache.catalina.util.ServerInfo;
38  import org.apache.commons.fileupload.FileItem;
39  import org.apache.commons.fileupload.DiskFileUpload;
40  
41  import org.talika.tms.Constants;
42  
43  /**
44  * Servlet that enables remote management of the web applications deployed
45  * within the same virtual host as this web application is.  Normally, this
46  * functionality will be protected by a security constraint in the web
47  * application deployment descriptor.  However, this requirement can be
48  * relaxed during testing.
49  * <p>
50  * The difference between the <code>ManagerServlet</code> and this
51  * Servlet is that this Servlet prints out a HTML interface which
52  * makes it easier to administrate.
53  * <p>
54  * However if you use a software that parses the output of
55  * <code>ManagerServlet</code you won't be able to upgrade
56  * to this Servlet since the output are not in the
57  * same format ar from <code>ManagerServlet</code>
58  *
59  * @author Bip Thelin
60  * @author Malcolm Edgar
61  * @author Glenn L. Nielsen
62  * @author Jose M. Palomar
63  * @version $Revision: 289 $, $Date: 2005-12-07 21:09:03 +0100 (mié 07 de dic de 2005) $
64  * @see ManagerXServlet
65  */
66  
67  public final class HTMLManagerXServlet extends ManagerXServlet {
68  
69      // --------------------------------------------------------- Public Methods
70  
71      /**
72       * Process a GET request for the specified resource.
73       *
74       * @param request The servlet request we are processing
75       * @param response The servlet response we are creating
76       *
77       * @exception IOException if an input/output error occurs
78       * @exception ServletException if a servlet-specified error occurs
79       */
80      public void doGet(HttpServletRequest request,
81                        HttpServletResponse response)
82          throws IOException, ServletException {
83  
84          // Identify the request parameters that we need
85          String command = request.getPathInfo();
86  
87          String vhost = request.getParameter("vhost");
88          String path = request.getParameter("path");
89          String deployPath = request.getParameter("deployPath");
90          String deployConfig = request.getParameter("deployConfig");
91          String deployWar = request.getParameter("deployWar");
92  
93          // Prepare our output writer to generate the response message
94          response.setContentType("text/html; charset=" + Constants.CHARSET);
95  
96          String message = "";
97          // Process the requested command
98          if (command == null || command.equals("/")) {
99          } else if (command.equals("/deploy")) {
100             message = deployInternal(vhost, deployConfig, deployPath, deployWar);
101         } else if (command.equals("/vhosts")) {
102         } else if (command.equals("/list")) {
103         } else if (command.equals("/reload")) {
104             message = reload(vhost, path);
105         } else if (command.equals("/undeploy")) {
106             message = undeploy(vhost, path);
107         } else if (command.equals("/sessions")) {
108             message = sessions(vhost, path);
109         } else if (command.equals("/start")) {
110             message = start(vhost, path);
111         } else if (command.equals("/stop")) {
112             message = stop(vhost, path);
113         } else {
114             message =
115                 sm.getString("managerServlet.unknownCommand",
116                              RequestUtil.filter(command));
117         }
118 
119         list(request, response, vhost, message);
120     }
121 
122     /**
123      * Process a POST request for the specified resource.
124      *
125      * @param request The servlet request we are processing
126      * @param response The servlet response we are creating
127      *
128      * @exception IOException if an input/output error occurs
129      * @exception ServletException if a servlet-specified error occurs
130      */
131     public void doPost(HttpServletRequest request,
132                       HttpServletResponse response)
133         throws IOException, ServletException {
134 
135         // Identify the request parameters that we need
136         String command = request.getPathInfo();
137 
138         if (command == null || !command.equals("/upload")) {
139             doGet(request,response);
140             return;
141         }
142 
143         // Prepare our output writer to generate the response message
144         response.setContentType("text/html; charset=" + Constants.CHARSET);
145 
146         String message = "";
147 
148         // Create a new file upload handler
149         DiskFileUpload upload = new DiskFileUpload();
150 
151         // Get the tempdir
152         File tempdir = (File) getServletContext().getAttribute
153             ("javax.servlet.context.tempdir");
154         // Set upload parameters
155         upload.setSizeMax(-1);
156         upload.setRepositoryPath(tempdir.getCanonicalPath());
157     
158         // Parse the request
159         String basename = null;
160         String war = null;
161         FileItem warUpload = null;
162         String vhost = null;
163         try {
164             List items = upload.parseRequest(request);
165         
166             // Process the uploaded fields
167             Iterator iter = items.iterator();
168             while (iter.hasNext()) {
169                 FileItem item = (FileItem) iter.next();
170         
171                 if (!item.isFormField()) {
172                     if (item.getFieldName().equals("deployWar") &&
173                         warUpload == null) {
174                         warUpload = item;
175                     } else {
176                         item.delete();
177                     }
178                 }
179                 else {
180                     if (item.getFieldName().equals("vhost")) {
181                         vhost = item.getString();
182                     }
183                 }
184             }
185             while (true) {
186                 if (vhost == null) {
187                     message = sm.getString
188                         ("managerServlet.invalidVirtualHost", vhost);
189                     break;
190                 }
191                 if (warUpload == null) {
192                     message = sm.getString
193                         ("htmlManagerServlet.deployUploadNoFile");
194                     break;
195                 }
196                 war = warUpload.getName();
197                 if (!war.toLowerCase().endsWith(".war")) {
198                     message = sm.getString
199                         ("htmlManagerServlet.deployUploadNotWar",war);
200                     break;
201                 }
202                 // Get the filename if uploaded name includes a path
203                 if (war.lastIndexOf('\\') >= 0) {
204                     war = war.substring(war.lastIndexOf('\\') + 1);
205                 }
206                 if (war.lastIndexOf('/') >= 0) {
207                     war = war.substring(war.lastIndexOf('/') + 1);
208                 }
209                 // Identify the appBase of the owning Host of this Context
210                 // (if any)
211                 Host host = (Host) engine.findChild(vhost);
212                 if (host == null) {
213                     message = sm.getString("managerServlet.invalidVirtualHost", vhost);
214                 }
215                 else {
216                 
217                     basename = war.substring(0, war.toLowerCase().indexOf(".war"));
218                     File file = new File(getAppBase(host), war);
219                     if (file.exists()) {
220                         message = sm.getString
221                             ("htmlManagerServlet.deployUploadWarExists",war);
222                         break;
223                     }
224                     String path = null;
225                     if (basename.equals("ROOT")) {
226                         path = "";
227                     } else {
228                         path = "/" + basename;
229                     }
230     
231                     if (!isServiced(host, path)) {
232                         addServiced(host, path);
233                         try {
234                             warUpload.write(file);
235                             // Perform new deployment
236                             check(host, path);
237                         } finally {
238                             removeServiced(host, path);
239                         }
240                     }
241                     
242                 }                
243                 break;
244             }
245         } catch(Exception e) {
246             message = sm.getString
247                 ("htmlManagerServlet.deployUploadFail", e.getMessage());
248             log(message, e);
249         } finally {
250             if (warUpload != null) {
251                 warUpload.delete();
252             }
253             warUpload = null;
254         }
255 
256         list(request, response, vhost, message);
257     }
258 
259     /**
260      * Deploy an application for the specified path from the specified
261      * web application archive.
262      *
263      * @param vhost Virtual host to be listed
264      * @param config URL of the context configuration file to be deployed
265      * @param path Context path of the application to be deployed
266      * @param war URL of the web application archive to be deployed
267      * @return message String
268      */
269     protected String deployInternal(String vhost, String config, String path, String war) {
270 
271         StringWriter stringWriter = new StringWriter();
272         PrintWriter printWriter = new PrintWriter(stringWriter);
273 
274         super.deploy(printWriter, vhost, config, path, war, false);
275 
276         return stringWriter.toString();
277     }
278 
279     /**
280      * Render a HTML list of the currently active Contexts in our virtual host,
281      * and memory and server status information.
282      *
283      * @param request The request
284      * @param response The response
285      * @param vhost Virtual host to be listed
286      * @param message a message to display
287      */
288     public void list(HttpServletRequest request,
289                      HttpServletResponse response,
290                      String vhost,
291                      String message) throws IOException {
292 
293         if (debug >= 1)
294             log("list: Listing contexts for virtual host '" +
295                 vhost + "'");
296 
297         Host host = null;
298         if (vhost != null && vhost.length() > 0) {
299 
300             host = (Host) engine.findChild(vhost);
301             if (host == null) {
302                 message = sm.getString("managerServlet.invalidVirtualHost", vhost);
303             }
304             
305         }
306         
307         PrintWriter writer = response.getWriter();
308 
309         // HTML Header Section
310         writer.print(Constants.HTML_HEADER_SECTION);
311 
312         // Body Header Section
313         Object[] args = new Object[2];
314         args[0] = request.getContextPath();
315         args[1] = sm.getString("htmlManagerServlet.title");
316         writer.print(MessageFormat.format
317                      (Constants.BODY_HEADER_SECTION, args));
318 
319         if (host == null) {
320 
321             // Manager Section
322             args = new Object[9];
323             args[0] = sm.getString("htmlManagerServlet.manager");
324             args[1] = response.encodeURL(request.getContextPath() + "/html/vhosts");
325             args[2] = sm.getString("htmlManagerServlet.vhosts");
326             args[3] = response.encodeURL
327                 (request.getContextPath() + "/" +
328                  sm.getString("htmlManagerServlet.helpHtmlManagerFile"));
329             args[4] = sm.getString("htmlManagerServlet.helpHtmlManager");
330             args[5] = response.encodeURL
331                 (request.getContextPath() + "/" +
332                  sm.getString("htmlManagerServlet.helpManagerFile"));
333             args[6] = sm.getString("htmlManagerServlet.helpManager");
334             args[7] = response.encodeURL
335                 (request.getContextPath() + "/status");
336             args[8] = sm.getString("statusServlet.title");
337             writer.print(MessageFormat.format(MANAGERX_SECTION, args));
338             
339             // Vhosts Header Section
340             args = new Object[4];
341             args[0] = sm.getString("htmlManagerServlet.vhostsTitle");
342             args[1] = sm.getString("htmlManagerServlet.vhostsName");
343             args[2] = sm.getString("htmlManagerServlet.vhostsDefault");
344             args[3] = sm.getString("htmlManagerServlet.vhostsTasks");
345             writer.print(MessageFormat.format(VHOSTS_HEADER_SECTION, args));
346             
347             // Vhosts Row Section
348             Container hosts[] = engine.findChildren();
349     
350             String defaultHostName = engine.getDefaultHost();
351             String vhostsList = sm.getString("htmlManagerServlet.vhostsList");
352             boolean isHighlighted = true;
353             String highlightColor = null;
354 
355             for (int i = 0; i < hosts.length; i++) {
356 
357                 String name = hosts[i].getName();
358                 boolean defaultHost = (name != null && name.equals(defaultHostName));
359                 isHighlighted = !isHighlighted;
360                 if(isHighlighted) {
361                     highlightColor = "#C3F3C3";
362                 } else {
363                     highlightColor = "#FFFFFF";
364                 }
365 
366                 args = new Object[5];
367                 args[0] = name;
368                 args[1] = new Boolean(defaultHost);
369                 args[2] = response.encodeURL
370                         (request.getContextPath() + "/html/list?vhost=" + name);
371                 args[3] = vhostsList;
372 
373                 args[4] = highlightColor;
374 
375                     writer.print
376                         (MessageFormat.format(VHOSTS_ROW_DETAILS_SECTION, args));
377                 
378             }
379             
380             writer.print(VHOSTS_FOOTER_SECTION);
381             
382         }
383         else {
384 
385             // Message Section
386             args = new Object[3];
387             args[0] = sm.getString("htmlManagerServlet.messageLabel");
388             args[1] = (message == null || message.length() == 0) ? "OK" : message;
389             writer.print(MessageFormat.format(Constants.MESSAGE_SECTION, args));
390     
391             // Manager Section
392             args = new Object[9];
393             args[0] = sm.getString("htmlManagerServlet.manager");
394             args[1] = response.encodeURL(request.getContextPath() +
395                                          "/html/list?vhost=" + vhost);
396             args[2] = sm.getString("htmlManagerServlet.list");
397             args[3] = response.encodeURL
398                 (request.getContextPath() + "/" +
399                  sm.getString("htmlManagerServlet.helpHtmlManagerFile"));
400             args[4] = sm.getString("htmlManagerServlet.helpHtmlManager");
401             args[5] = response.encodeURL
402                 (request.getContextPath() + "/" +
403                  sm.getString("htmlManagerServlet.helpManagerFile"));
404             args[6] = sm.getString("htmlManagerServlet.helpManager");
405             args[7] = response.encodeURL
406                 (request.getContextPath() + "/status");
407             args[8] = sm.getString("statusServlet.title");
408             writer.print(MessageFormat.format(MANAGERX_SECTION, args));
409     
410             // Apps Header Section
411             args = new Object[6];
412             args[0] = sm.getString("htmlManagerServlet.appsTitle") + " - " + vhost;
413             args[1] = sm.getString("htmlManagerServlet.appsPath");
414             args[2] = sm.getString("htmlManagerServlet.appsName");
415             args[3] = sm.getString("htmlManagerServlet.appsAvailable");
416             args[4] = sm.getString("htmlManagerServlet.appsSessions");
417             args[5] = sm.getString("htmlManagerServlet.appsTasks");
418             writer.print(MessageFormat.format(APPS_HEADER_SECTION, args));
419     
420             // Apps Row Section
421             // Create sorted map of deployed applications context paths.
422             Container children[] = host.findChildren();
423             String contextPaths[] = new String[children.length];
424             for (int i = 0; i < children.length; i++)
425                 contextPaths[i] = children[i].getName();
426             
427             TreeMap sortedContextPathsMap = new TreeMap();
428     
429             for (int i = 0; i < contextPaths.length; i++) {
430                 String displayPath = contextPaths[i];
431                 sortedContextPathsMap.put(displayPath, contextPaths[i]);
432             }
433     
434             String appsStart = sm.getString("htmlManagerServlet.appsStart");
435             String appsStop = sm.getString("htmlManagerServlet.appsStop");
436             String appsReload = sm.getString("htmlManagerServlet.appsReload");
437             String appsUndeploy = sm.getString("htmlManagerServlet.appsUndeploy");
438     
439             Iterator iterator = sortedContextPathsMap.entrySet().iterator();
440             boolean isHighlighted = true;
441             String highlightColor = null;
442 
443             while (iterator.hasNext()) {
444                 // Bugzilla 34818, alternating row colors
445                 isHighlighted = !isHighlighted;
446                 if(isHighlighted) {
447                     highlightColor = "#C3F3C3";
448                 } else {
449                     highlightColor = "#FFFFFF";
450                 }
451 
452                 Map.Entry entry = (Map.Entry) iterator.next();
453                 String displayPath = (String) entry.getKey();
454                 String contextPath = (String) entry.getKey();
455                 Context context = (Context) host.findChild(contextPath);
456                 if (displayPath.equals("")) {
457                     displayPath = "/";
458                 }
459     
460                 if (context != null ) {
461                     args = new Object[6];
462                     args[0] = displayPath;
463                     args[1] = context.getDisplayName();
464                     if (args[1] == null) {
465                         args[1] = "&nbsp;";
466                     }
467                     args[2] = new Boolean(context.getAvailable());
468                     args[3] = response.encodeURL
469                         (request.getContextPath() +
470                          "/html/sessions?vhost=" + vhost + "&path=" + displayPath);
471                     if (context.getManager() != null) {
472                         args[4] = new Integer
473                             (context.getManager().getActiveSessions());
474                     } else {
475                         args[4] = new Integer(0);
476                     }
477 
478                     args[5] = highlightColor;
479 
480                     writer.print
481                         (MessageFormat.format(APPS_ROW_DETAILS_SECTION, args));
482     
483                     args = new Object[9];
484                     args[0] = response.encodeURL
485                         (request.getContextPath() +
486                          "/html/start?vhost=" + vhost + "&path=" + displayPath);
487                     args[1] = appsStart;
488                     args[2] = response.encodeURL
489                         (request.getContextPath() +
490                          "/html/stop?vhost=" + vhost + "&path=" + displayPath);
491                     args[3] = appsStop;
492                     args[4] = response.encodeURL
493                         (request.getContextPath() +
494                          "/html/reload?vhost=" + vhost + "&path=" + displayPath);
495                     args[5] = appsReload;
496                     args[6] = response.encodeURL
497                         (request.getContextPath() +
498                          "/html/undeploy?vhost=" + vhost + "&path=" + displayPath);
499                     args[7] = appsUndeploy;
500                     
501                     args[8] = highlightColor;
502 
503                     if (context.getPath().equals(this.context.getPath())) {
504                         writer.print(MessageFormat.format(
505                             MANAGER_APP_ROW_BUTTON_SECTION, args));
506                     } else if (context.getAvailable()) {
507                         writer.print(MessageFormat.format(
508                             STARTED_APPS_ROW_BUTTON_SECTION, args));
509                     } else {
510                         writer.print(MessageFormat.format(
511                             STOPPED_APPS_ROW_BUTTON_SECTION, args));
512                     }
513     
514                 }
515             }
516     
517             // Deploy Section
518             args = new Object[8];
519             args[0] = sm.getString("htmlManagerServlet.deployTitle");
520             args[1] = sm.getString("htmlManagerServlet.deployServer");
521             args[2] = response.encodeURL(request.getContextPath() + "/html/deploy");
522             args[3] = vhost; 
523             args[4] = sm.getString("htmlManagerServlet.deployPath");
524             args[5] = sm.getString("htmlManagerServlet.deployConfig");
525             args[6] = sm.getString("htmlManagerServlet.deployWar");
526             args[7] = sm.getString("htmlManagerServlet.deployButton");
527             writer.print(MessageFormat.format(DEPLOY_SECTION, args));
528     
529             args = new Object[5];
530             args[0] = sm.getString("htmlManagerServlet.deployUpload");
531             args[1] = response.encodeURL(request.getContextPath() + "/html/upload");
532             args[2] = vhost;
533             args[3] = sm.getString("htmlManagerServlet.deployUploadFile");
534             args[4] = sm.getString("htmlManagerServlet.deployButton");
535             writer.print(MessageFormat.format(UPLOAD_SECTION, args));
536 
537         }
538 
539         // Server Header Section
540         args = new Object[7];
541         args[0] = sm.getString("htmlManagerServlet.serverTitle");
542         args[1] = sm.getString("htmlManagerServlet.serverVersion");
543         args[2] = sm.getString("htmlManagerServlet.serverJVMVersion");
544         args[3] = sm.getString("htmlManagerServlet.serverJVMVendor");
545         args[4] = sm.getString("htmlManagerServlet.serverOSName");
546         args[5] = sm.getString("htmlManagerServlet.serverOSVersion");
547         args[6] = sm.getString("htmlManagerServlet.serverOSArch");
548         writer.print(MessageFormat.format
549                      (Constants.SERVER_HEADER_SECTION, args));
550 
551         // Server Row Section
552         args = new Object[6];
553         args[0] = ServerInfo.getServerInfo();
554         args[1] = System.getProperty("java.runtime.version");
555         args[2] = System.getProperty("java.vm.vendor");
556         args[3] = System.getProperty("os.name");
557         args[4] = System.getProperty("os.version");
558         args[5] = System.getProperty("os.arch");
559         writer.print(MessageFormat.format(Constants.SERVER_ROW_SECTION, args));
560 
561         // HTML Tail Section
562         writer.print(Constants.HTML_TAIL_SECTION);
563 
564         // Finish up the response
565         writer.flush();
566         writer.close();
567     }
568 
569     /**
570      * Reload the web application at the specified context path.
571      *
572      * @see ManagerXServlet#reload(PrintWriter, String, String)
573      *
574      * @param vhost Virtual host to be listed
575      * @param path Context path of the application to be restarted
576      * @return message String
577      */
578     protected String reload(String vhost, String path) {
579 
580         StringWriter stringWriter = new StringWriter();
581         PrintWriter printWriter = new PrintWriter(stringWriter);
582 
583         super.reload(printWriter, vhost, path);
584 
585         return stringWriter.toString();
586     }
587 
588     /**
589      * Undeploy the web application at the specified context path.
590      *
591      * @see ManagerXServlet#undeploy(PrintWriter, String, String)
592      *
593      * @param vhost Virtual host to be listed
594      * @param path Context path of the application to be undeployd
595      * @return message String
596      */
597     protected String undeploy(String vhost, String path) {
598 
599         StringWriter stringWriter = new StringWriter();
600         PrintWriter printWriter = new PrintWriter(stringWriter);
601 
602         super.undeploy(printWriter, vhost, path);
603 
604         return stringWriter.toString();
605     }
606 
607     /**
608      * Display session information and invoke list.
609      *
610      * @see ManagerXServlet#sessions(PrintWriter, String, String)
611      *
612      * @param vhost Virtual host to be listed
613      * @param path Context path of the application to list session information
614      * @return message String
615      */
616     public String sessions(String vhost, String path) {
617 
618         StringWriter stringWriter = new StringWriter();
619         PrintWriter printWriter = new PrintWriter(stringWriter);
620 
621         super.sessions(printWriter, vhost, path);
622 
623         return stringWriter.toString();
624     }
625 
626     /**
627      * Start the web application at the specified context path.
628      *
629      * @see ManagerXServlet#start(PrintWriter, String, String)
630      *
631      * @param vhost Virtual host to be listed
632      * @param path Context path of the application to be started
633      * @return message String
634      */
635     public String start(String vhost, String path) {
636 
637         StringWriter stringWriter = new StringWriter();
638         PrintWriter printWriter = new PrintWriter(stringWriter);
639 
640         super.start(printWriter, vhost, path);
641 
642         return stringWriter.toString();
643     }
644 
645     /**
646      * Stop the web application at the specified context path.
647      *
648      * @see ManagerXServlet#stop(PrintWriter, String, String)
649      *
650      * @param vhost Virtual host to be listed
651      * @param path Context path of the application to be stopped
652      * @return message String
653      */
654     protected String stop(String vhost, String path) {
655 
656         StringWriter stringWriter = new StringWriter();
657         PrintWriter printWriter = new PrintWriter(stringWriter);
658 
659         super.stop(printWriter, vhost, path);
660 
661         return stringWriter.toString();
662     }
663 
664     // ------------------------------------------------------ Private Constants
665 
666     // These HTML sections are broken in relatively small sections, because of
667     // limited number of subsitutions MessageFormat can process
668     // (maximium of 10).
669 
670     private static final String MANAGERX_SECTION =
671         "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n" +
672         "<tr>\n" +
673         " <td colspan=\"4\" class=\"title\">{0}</td>\n" +
674         "</tr>\n" +
675         " <tr>\n" +
676         "  <td class=\"row-left\"><a href=\"{1}\">{2}</a></td>\n" +
677         "  <td class=\"row-center\"><a href=\"{3}\">{4}</a></td>\n" +
678         "  <td class=\"row-center\"><a href=\"{5}\">{6}</a></td>\n" +
679         "  <td class=\"row-right\"><a href=\"{7}\">{8}</a></td>\n" +
680         " </tr>\n" +
681         "</table>\n" +
682         "<br>\n" +
683         "\n";
684 
685     private static final String VHOSTS_HEADER_SECTION =
686         "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n" +
687         "<tr>\n" +
688         " <td colspan=\"3\" class=\"title\">{0}</td>\n" +
689         "</tr>\n" +
690         "<tr>\n" +
691         " <td class=\"header-left\"><small>{1}</small></td>\n" +
692         " <td class=\"header-center\"><small>{2}</small></td>\n" +
693         " <td class=\"header-left\"><small>{3}</small></td>\n" +
694         "</tr>\n";
695 
696     private static final String VHOSTS_ROW_DETAILS_SECTION =
697         "<tr>\n" +
698         " <td class=\"row-left\" bgcolor=\"{4}\"><small>{0}</small></td>\n" +
699         " <td class=\"row-center\" bgcolor=\"{4}\"><small>{1}</small></td>\n" +
700         " <td class=\"row-left\" bgcolor=\"{4}\"><small><a href=\"{2}\">{3}</a></small></td>\n" +
701         "</tr>\n";
702 
703     private static final String VHOSTS_FOOTER_SECTION =
704         "</table>\n" +
705         "<br>\n";
706     
707     private static final String APPS_HEADER_SECTION =
708         "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n" +
709         "<tr>\n" +
710         " <td colspan=\"5\" class=\"title\">{0}</td>\n" +
711         "</tr>\n" +
712         "<tr>\n" +
713         " <td class=\"header-left\"><small>{1}</small></td>\n" +
714         " <td class=\"header-left\"><small>{2}</small></td>\n" +
715         " <td class=\"header-center\"><small>{3}</small></td>\n" +
716         " <td class=\"header-center\"><small>{4}</small></td>\n" +
717         " <td class=\"header-center\"><small>{5}</small></td>\n" +
718         "</tr>\n";
719 
720     private static final String APPS_ROW_DETAILS_SECTION =
721         "<tr>\n" +
722         " <td class=\"row-left\" bgcolor=\"{5}\"><small><a href=\"{0}\">{0}</a></small></td>\n" +
723         " <td class=\"row-left\" bgcolor=\"{5}\"><small>{1}</small></td>\n" +
724         " <td class=\"row-center\" bgcolor=\"{5}\"><small>{2}</small></td>\n" +
725         " <td class=\"row-center\" bgcolor=\"{5}\"><small><a href=\"{3}\">{4}</a></small></td>\n";
726             
727     private static final String MANAGER_APP_ROW_BUTTON_SECTION =
728         " <td class=\"row-left\" bgcolor=\"{8}\">\n" +
729         "  <small>\n" +
730         "  &nbsp;{1}&nbsp;\n" +
731         "  &nbsp;{3}&nbsp;\n" +
732         "  &nbsp;{5}&nbsp;\n" +
733         "  &nbsp;{7}&nbsp;\n" +
734         "  </small>\n" +
735         " </td>\n" +
736         "</tr>\n";
737 
738     private static final String STARTED_APPS_ROW_BUTTON_SECTION =
739         " <td class=\"row-left\" bgcolor=\"{8}\">\n" +
740         "  <small>\n" +
741         "  &nbsp;{1}&nbsp;\n" +
742         "  &nbsp;<a href=\"{2}\" onclick=\"return(confirm('''Are you sure?'''))\">{3}</a>&nbsp;\n" +
743         "  &nbsp;<a href=\"{4}\" onclick=\"return(confirm('''Are you sure?'''))\">{5}</a>&nbsp;\n" +
744         "  &nbsp;<a href=\"{6}\" onclick=\"return(confirm('''Are you sure? This will delete the application.'''))\">{7}</a>&nbsp;\n" +
745         "  </small>\n" +
746         " </td>\n" +
747         "</tr>\n";
748 
749     private static final String STOPPED_APPS_ROW_BUTTON_SECTION =
750         " <td class=\"row-left\" bgcolor=\"{8}\">\n" +
751         "  <small>\n" +
752         "  &nbsp;<a href=\"{0}\" onclick=\"return(confirm('''Are you sure?'''))\">{1}</a>&nbsp;\n" +
753         "  &nbsp;{3}&nbsp;\n" +
754         "  &nbsp;{5}&nbsp;\n" +
755         "  &nbsp;<a href=\"{6}\" onclick=\"return(confirm('''Are you sure? This will delete the application.'''))\">{7}</a>&nbsp;\n" +
756         "  </small>\n" +
757         " </td>\n" +
758         "</tr>\n";
759 
760     private static final String DEPLOY_SECTION =
761         "</table>\n" +
762         "<br>\n" +
763         "<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n" +
764         "<tr>\n" +
765         " <td colspan=\"2\" class=\"title\">{0}</td>\n" +
766         "</tr>\n" +
767         "<tr>\n" +
768         " <td colspan=\"2\" class=\"header-left\"><small>{1}</small></td>\n" +
769         "</tr>\n" +
770         "<tr>\n" +
771         " <td colspan=\"2\">\n" +
772         "<form method=\"get\" action=\"{2}\">\n" +
773         "<input type=\"hidden\" name=\"vhost\" value=\"{3}\">\n" +
774         "<table cellspacing=\"0\" cellpadding=\"3\">\n" +
775         "<tr>\n" +
776         " <td class=\"row-right\">\n" +
777         "  <small>{4}</small>\n" +
778         " </td>\n" +
779         " <td class=\"row-left\">\n" +
780         "  <input type=\"text\" name=\"deployPath\" size=\"20\">\n" +
781         " </td>\n" +
782         "</tr>\n" +
783         "<tr>\n" +
784         " <td class=\"row-right\">\n" +
785         "  <small>{5}</small>\n" +
786         " </td>\n" +
787         " <td class=\"row-left\">\n" +
788         "  <input type=\"text\" name=\"deployConfig\" size=\"20\">\n" +
789         " </td>\n" +
790         "</tr>\n" +
791         "<tr>\n" +
792         " <td class=\"row-right\">\n" +
793         "  <small>{6}</small>\n" +
794         " </td>\n" +
795         " <td class=\"row-left\">\n" +
796         "  <input type=\"text\" name=\"deployWar\" size=\"40\">\n" +
797         " </td>\n" +
798         "</tr>\n" +
799         "<tr>\n" +
800         " <td class=\"row-right\">\n" +
801         "  &nbsp;\n" +
802         " </td>\n" +
803         " <td class=\"row-left\">\n" +
804         "  <input type=\"submit\" value=\"{7}\">\n" +
805         " </td>\n" +
806         "</tr>\n" +
807         "</table>\n" +
808         "</form>\n" +
809         "</td>\n" +
810         "</tr>\n";
811 
812     private static final String UPLOAD_SECTION =
813         "<tr>\n" +
814         " <td colspan=\"2\" class=\"header-left\"><small>{0}</small></td>\n" +
815         "</tr>\n" +
816         "<tr>\n" +
817         " <td colspan=\"2\">\n" +
818         "<form action=\"{1}\" method=\"post\" " +
819         "enctype=\"multipart/form-data\">\n" +
820         "<input type=\"hidden\" name=\"vhost\" value=\"{2}\">\n" +
821         "<table cellspacing=\"0\" cellpadding=\"3\">\n" +
822         "<tr>\n" +
823         " <td class=\"row-right\">\n" +
824         "  <small>{3}</small>\n" +
825         " </td>\n" +
826         " <td class=\"row-left\">\n" +
827         "  <input type=\"file\" name=\"deployWar\" size=\"40\">\n" +
828         " </td>\n" +
829         "</tr>\n" +
830         "<tr>\n" +
831         " <td class=\"row-right\">\n" +
832         "  &nbsp;\n" +
833         " </td>\n" +
834         " <td class=\"row-left\">\n" +
835         "  <input type=\"submit\" value=\"{4}\">\n" +
836         " </td>\n" +
837         "</tr>\n" +
838         "</table>\n" +
839         "</form>\n" +
840         "</table>\n" +
841         "<br>\n" +
842         "\n";
843 
844 }