View Javadoc

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