View Javadoc

1   /*
2    * $Header$
3    * $Revision: 173 $
4    * $Date: 2004-07-29 20:25:08 +0200 (jue 29 de jul de 2004) $
5    *
6    * ====================================================================
7    *
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 1999 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer.
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution, if
26   *    any, must include the following acknowlegement:
27   *       "This product includes software developed by the
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowlegement may appear in the software itself,
30   *    if and wherever such third-party acknowlegements normally appear.
31   *
32   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
33   *    Foundation" must not be used to endorse or promote products derived
34   *    from this software without prior written permission. For written
35   *    permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache"
38   *    nor may "Apache" appear in their names without prior written
39   *    permission of the Apache Group.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   *
60   * [Additional notices, if required by prior licensing conditions]
61   *
62   */
63  
64  
65  package org.apache.catalina.servlets;
66  
67  
68  import java.io.IOException;
69  import java.io.PrintWriter;
70  import java.net.URL;
71  import javax.servlet.ServletException;
72  import javax.servlet.UnavailableException;
73  import javax.servlet.http.HttpServlet;
74  import javax.servlet.http.HttpServletRequest;
75  import javax.servlet.http.HttpServletResponse;
76  
77  import org.apache.catalina.Container;
78  import org.apache.catalina.ContainerServlet;
79  import org.apache.catalina.Context;
80  import org.apache.catalina.Deployer;
81  import org.apache.catalina.Globals;
82  import org.apache.catalina.Session;
83  import org.apache.catalina.Wrapper;
84  import org.apache.catalina.util.StringManager;
85  
86  import org.apache.catalina.Engine;
87  import org.talika.tms.Constants;
88  
89  /**
90   * Servlet that enables remote management of the web applications installed
91   * within the same virtual host as this web application is.  Normally, this
92   * functionality will be protected by a security constraint in the web
93   * application deployment descriptor.  However, this requirement can be
94   * relaxed during testing.
95   *
96   * @author Craig R. McClanahan
97   * @author Jose M. Palomar
98   * @version $Revision: 173 $ $Date: 2004-07-29 20:25:08 +0200 (jue 29 de jul de 2004) $
99   */
100 
101 public class ManagerXServlet extends HttpServlet implements ContainerServlet {
102 
103 
104     // ----------------------------------------------------- Instance Variables
105 
106 
107     /**
108      * The Context container associated with our web application.
109      */
110     protected Context context = null;
111 
112 
113     /**
114      * The debugging detail level for this servlet.
115      */
116     protected int debug = 0;
117 
118 
119     /**
120      * The Engine container of all our vhosts
121      */
122     protected Engine engine = null;
123 
124     /**
125      * The string manager for this package.
126      */
127     protected static StringManager sm = 
128         StringManager.getManager(Constants.Package);
129 
130 
131     /**
132      * The Wrapper container associated with this servlet.
133      */
134     protected Wrapper wrapper = null;
135 
136 
137     // ----------------------------------------------- ContainerServlet Methods
138 
139 
140     /**
141      * Return the Wrapper with which we are associated.
142      */
143     public Wrapper getWrapper() {
144 
145         return (this.wrapper);
146 
147     }
148 
149 
150     /**
151      * Set the Wrapper with which we are associated.
152      *
153      * @param wrapper The new wrapper
154      */
155     public void setWrapper(Wrapper wrapper) {
156 
157         this.wrapper = wrapper;
158         if (wrapper == null) {
159             context = null;
160             engine = null;
161         } else {
162             context = (Context) wrapper.getParent();
163             engine = (Engine) context.getParent().getParent();
164         }
165 
166     }
167 
168 
169     // --------------------------------------------------------- Public Methods
170 
171 
172     /**
173      * Finalize this servlet.
174      */
175     public void destroy() {
176 
177         ;       // No actions necessary
178 
179     }
180 
181 
182     /**
183      * Process a GET request for the specified resource.
184      *
185      * @param request The servlet request we are processing
186      * @param response The servlet response we are creating
187      *
188      * @exception IOException if an input/output error occurs
189      * @exception ServletException if a servlet-specified error occurs
190      */
191     public void doGet(HttpServletRequest request,
192                       HttpServletResponse response)
193         throws IOException, ServletException {
194 
195         // Verify that we were not accessed using the invoker servlet
196         if (request.getAttribute(Globals.INVOKED_ATTR) != null)
197             throw new UnavailableException
198                 (sm.getString("managerServlet.cannotInvoke"));
199 
200         // Identify the request parameters that we need
201         String command = request.getPathInfo();
202         if (command == null)
203             command = request.getServletPath();
204         String vhost = request.getParameter("vhost");
205         String path = request.getParameter("path");
206         String war = request.getParameter("war");
207 
208         // Prepare our output writer to generate the response message
209         response.setContentType("text/plain");
210         PrintWriter writer = response.getWriter();
211 
212         // Process the requested command
213         if (command == null) {
214             writer.println(sm.getString("managerServlet.noCommand"));
215         } else if (command.equals("/vhosts")) {
216             vhosts(writer);
217         } else if (command.equals("/install")) {
218             install(writer, vhost, path, war);
219         } else if (command.equals("/list")) {
220             list(writer, vhost);
221         } else if (command.equals("/reload")) {
222             reload(writer, vhost, path);
223         } else if (command.equals("/remove")) {
224             remove(writer, vhost, path);
225         } else if (command.equals("/sessions")) {
226             sessions(writer, vhost, path);
227         } else if (command.equals("/start")) {
228             start(writer, vhost, path);
229         } else if (command.equals("/stop")) {
230             stop(writer, vhost, path);
231         } else {
232             writer.println(sm.getString("managerServlet.unknownCommand",
233                                         command));
234         }
235 
236         // Finish up the response
237         writer.flush();
238         writer.close();
239 
240     }
241 
242 
243     /**
244      * Initialize this servlet.
245      */
246     public void init() throws ServletException {
247 
248         // Ensure that our ContainerServlet properties have been set
249         if ((wrapper == null) || (context == null))
250             throw new UnavailableException
251                 (sm.getString("managerServlet.noWrapper"));
252 
253         // Verify that we were not accessed using the invoker servlet
254         String servletName = getServletConfig().getServletName();
255         if (servletName == null)
256             servletName = "";
257         if (servletName.startsWith("org.apache.catalina.INVOKER."))
258             throw new UnavailableException
259                 (sm.getString("managerServlet.cannotInvoke"));
260 
261         // Set our properties from the initialization parameters
262         String value = null;
263         try {
264             value = getServletConfig().getInitParameter("debug");
265             debug = Integer.parseInt(value);
266         } catch (Throwable t) {
267             ;
268         }
269 
270 
271         // Log debugging messages as necessary
272         if (debug >= 1) {
273             log("init: Associated with Deployer '" + context.getParent().getName() + "'");
274         }
275 
276     }
277 
278 
279 
280     // -------------------------------------------------------- Private Methods
281 
282 
283     /**
284      * Render a list of the currently active vhosts.
285      *
286      * @param writer Writer to render to
287      */
288     protected void vhosts(PrintWriter writer) {
289 
290         if (debug >= 1)
291             log("list: Listing virtual hosts for engine '" +
292                 engine.getName() + "'");
293 
294         writer.println(sm.getString("managerServlet.vhosts",
295                                     engine.getName()));
296         
297         Container hosts[] = engine.findChildren();
298         for (int i = 0; i < hosts.length; i++) {            
299             writer.println(sm.getString("managerServlet.hostitem",
300                                         hosts[i].getName()));            
301         }
302         
303     }
304     
305     /**
306      * Install an application for the specified path from the specified
307      * web application archive.
308      *
309      * @param writer Writer to render results to
310      * @param vhost Virtual host of the application to be installed
311      * @param path Context path of the application to be installed
312      * @param war URL of the web application archive to be installed
313      */
314     protected void install(PrintWriter writer, String vhost, String path, String war) {
315 
316         if (debug >= 1)
317             log("install: Installing web application at '" + vhost + ":" + path +
318                 "' from '" + war + "'");
319 
320         if((vhost == null) || (vhost.equals(""))) {
321             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
322             return;
323         }        
324         Deployer deployer = (Deployer) engine.findChild(vhost);
325         if (deployer == null) {
326             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
327             return;                
328         }
329         
330         if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
331             writer.println(sm.getString("managerServlet.invalidPath", path));
332             return;
333         }
334         String displayPath = path;
335         if( path.equals("/") )
336             path = "";
337         if ((war == null) ||
338             (!war.startsWith("file:") && !war.startsWith("jar:"))) {
339             writer.println(sm.getString("managerServlet.invalidWar", war));
340             return;
341         }
342 
343         try {
344             Context context =  deployer.findDeployedApp(path);
345             if (context != null) {
346                 writer.println(sm.getString("managerServlet.alreadyContext",
347                                             displayPath));
348                 return;
349             }
350             deployer.install(path, new URL(war));
351             writer.println(sm.getString("managerServlet.installed", displayPath));
352         } catch (Throwable t) {
353             getServletContext().log("ManagerServlet.install[" + displayPath + "]", t);
354             writer.println(sm.getString("managerServlet.exception",
355                                         t.toString()));
356         }
357 
358     }
359 
360 
361     /**
362      * Render a list of the currently active Contexts in selected virtual host.
363      *
364      * @param writer Writer to render to
365      * @param vhost Virtual host to be listed
366      */
367     protected void list(PrintWriter writer, String vhost) {
368 
369         if (debug >= 1)
370             log("list: Listing contexts for virtual host '" +
371                 vhost + "'");
372 
373         if((vhost == null) || (vhost.equals(""))) {
374             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
375             return;
376         }        
377         Deployer deployer = (Deployer) engine.findChild(vhost);
378         if (deployer == null) {
379             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
380             return;                
381         }
382         
383         writer.println(sm.getString("managerServlet.listed",
384                                     deployer.getName()));
385         String contextPaths[] = deployer.findDeployedApps();
386         for (int i = 0; i < contextPaths.length; i++) {
387             Context context = deployer.findDeployedApp(contextPaths[i]);
388             String displayPath = contextPaths[i];
389             if( displayPath.equals("") )
390                 displayPath = "/";
391             if (context != null ) {
392                 if (context.getAvailable()) {
393                     writer.println(sm.getString("managerServlet.listitem",
394                                                 displayPath,
395                                                 "running",
396                                       "" + context.getManager().findSessions().length));
397                 } else {
398                     writer.println(sm.getString("managerServlet.listitem",
399                                                 displayPath,
400                                                 "stopped",
401                                                 "0"));
402                 }
403             }
404         }
405     }
406 
407 
408     /**
409      * Reload the web application at the specified context path.
410      *
411      * @param writer Writer to render to
412      * @param vhost Virtual host of the application to be restarted
413      * @param path Context path of the application to be restarted
414      */
415     protected void reload(PrintWriter writer, String vhost, String path) {
416 
417         if (debug >= 1)
418             log("restart: Reloading web application at '" + vhost + ":" + path + "'");
419 
420         if((vhost == null) || (vhost.equals(""))) {
421             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
422             return;
423         }        
424         Deployer deployer = (Deployer) engine.findChild(vhost);
425         if (deployer == null) {
426             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
427             return;                
428         }
429         
430         if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
431             writer.println(sm.getString("managerServlet.invalidPath", path));
432             return;
433         }
434         String displayPath = path;
435         if( path.equals("/") )
436             path = "";
437 
438         try {
439             Context context = deployer.findDeployedApp(path);
440             if (context == null) {
441                 writer.println(sm.getString("managerServlet.noContext", displayPath));
442             return;
443             }
444             context.reload();
445             writer.println(sm.getString("managerServlet.reloaded", displayPath));
446         } catch (Throwable t) {
447             getServletContext().log("ManagerServlet.reload[" + displayPath + "]", t);
448             writer.println(sm.getString("managerServlet.exception",
449                                         t.toString()));
450         }
451 
452     }
453 
454 
455     /**
456      * Remove the web application at the specified context path.
457      *
458      * @param writer Writer to render to
459      * @param vhost Virtual host of the application to be removed
460      * @param path Context path of the application to be removed
461      */
462     protected void remove(PrintWriter writer, String vhost, String path) {
463 
464         if (debug >= 1)
465             log("remove: Removing web application at '" + vhost + ":" + path + "'");
466 
467         if((vhost == null) || (vhost.equals(""))) {
468             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
469             return;
470         }        
471         Deployer deployer = (Deployer) engine.findChild(vhost);
472         if (deployer == null) {
473             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
474             return;                
475         }
476         
477         if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
478             writer.println(sm.getString("managerServlet.invalidPath", path));
479             return;
480         }
481         String displayPath = path;
482         if( path.equals("/") )
483             path = "";
484 
485         try {
486             Context context = deployer.findDeployedApp(path);
487             if (context == null) {
488                 writer.println(sm.getString("managerServlet.noContext", displayPath));
489                 return;
490             }
491             deployer.remove(path);
492             writer.println(sm.getString("managerServlet.removed", displayPath));
493         } catch (Throwable t) {
494             getServletContext().log("ManagerServlet.remove[" + displayPath + "]",
495                                     t);
496             writer.println(sm.getString("managerServlet.exception",
497                                         t.toString()));
498         }
499 
500     }
501 
502 
503     /**
504      * Session information for the web application at the specified context path.
505      * Displays a profile of session MaxInactiveInterval timeouts listing number
506      * of sessions for each 10 minute timeout interval up to 10 hours.
507      *
508      * @param writer Writer to render to
509      * @param vhost Virtual host of the application to list session information for
510      * @param path Context path of the application to list session information for
511      */
512     protected void sessions(PrintWriter writer, String vhost, String path) {
513 
514         if (debug >= 1)
515             log("sessions: Session information for web application at '" + vhost + ":" + path + "'");
516 
517         if((vhost == null) || (vhost.equals(""))) {
518             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
519             return;
520         }        
521         Deployer deployer = (Deployer) engine.findChild(vhost);
522         if (deployer == null) {
523             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
524             return;                
525         }
526         
527         if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
528             writer.println(sm.getString("managerServlet.invalidPath", path));
529             return;
530         }
531         String displayPath = path;
532         if( path.equals("/") )
533             path = "";
534         try {
535             Context context = deployer.findDeployedApp(path);
536             if (context == null) {
537                 writer.println(sm.getString("managerServlet.noContext", displayPath));
538                 return;
539             }
540             writer.println(sm.getString("managerServlet.sessions", displayPath));
541             writer.println(sm.getString("managerServlet.sessiondefaultmax",
542                                 "" + context.getManager().getMaxInactiveInterval()/60));
543             Session [] sessions = context.getManager().findSessions();
544             int [] timeout = new int[60];
545             int notimeout = 0;
546             for (int i = 0; i < sessions.length; i++) {
547                 int time = sessions[i].getMaxInactiveInterval()/(10*60);
548                 if (time < 0)
549                     notimeout++;
550                 else if (time >= timeout.length)
551                     timeout[timeout.length-1]++;
552                 else
553                     timeout[time]++;
554             }
555             if (timeout[0] > 0)
556                 writer.println(sm.getString("managerServlet.sessiontimeout",
557                                             "<10" + timeout[0]));
558             for (int i = 1; i < timeout.length-1; i++) {
559                 if (timeout[i] > 0)
560                     writer.println(sm.getString("managerServlet.sessiontimeout",
561                                      "" + (i)*10 + " - <" + (i+1)*10,
562                                                 "" + timeout[i]));
563             }
564             if (timeout[timeout.length-1] > 0)
565                 writer.println(sm.getString("managerServlet.sessiontimeout",
566                                             ">=" + timeout.length*10,
567                                             "" + timeout[timeout.length-1]));
568             if (notimeout > 0)
569                 writer.println(sm.getString("managerServlet.sessiontimeout",
570                                             "unlimited","" + notimeout));
571         } catch (Throwable t) {
572             getServletContext().log("ManagerServlet.sessions[" + displayPath + "]",
573                                     t);
574             writer.println(sm.getString("managerServlet.exception",
575                                         t.toString()));
576         }
577 
578     }
579 
580     /**
581      * Start the web application at the specified context path.
582      *
583      * @param writer Writer to render to
584      * @param vhost Virtual host of the application to be started
585      * @param path Context path of the application to be started
586      */
587     protected void start(PrintWriter writer, String vhost, String path) {
588 
589         if (debug >= 1)
590             log("start: Starting web application at '" + vhost + ":" + path + "'");
591 
592         if((vhost == null) || (vhost.equals(""))) {
593             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
594             return;
595         }        
596         Deployer deployer = (Deployer) engine.findChild(vhost);
597         if (deployer == null) {
598             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
599             return;                
600         }
601         
602         if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
603             writer.println(sm.getString("managerServlet.invalidPath", path));
604             return;
605         }
606         String displayPath = path;
607         if( path.equals("/") )
608             path = "";
609 
610         try {
611             Context context = deployer.findDeployedApp(path);
612             if (context == null) {
613                 writer.println(sm.getString("managerServlet.noContext", displayPath));
614                 return;
615             }
616             deployer.start(path);
617             if (context.getAvailable())
618                 writer.println
619                     (sm.getString("managerServlet.started", displayPath));
620             else
621                 writer.println
622                     (sm.getString("managerServlet.startFailed", displayPath));
623         } catch (Throwable t) {
624             getServletContext().log
625                 (sm.getString("managerServlet.startFailed", displayPath), t);
626             writer.println
627                 (sm.getString("managerServlet.startFailed", displayPath));
628             writer.println(sm.getString("managerServlet.exception",
629                                         t.toString()));
630         }
631 
632     }
633 
634 
635     /**
636      * Stop the web application at the specified context path.
637      *
638      * @param writer Writer to render to
639      * @param vhost Virtual host of the application to be stopped
640      * @param path Context path of the application to be stopped
641      */
642     protected void stop(PrintWriter writer, String vhost, String path) {
643 
644         if (debug >= 1)
645             log("stop: Stopping web application at '" + vhost + ":" + path + "'");
646 
647         if((vhost == null) || (vhost.equals(""))) {
648             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
649             return;
650         }        
651         Deployer deployer = (Deployer) engine.findChild(vhost);
652         if (deployer == null) {
653             writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
654             return;                
655         }
656         
657         if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
658             writer.println(sm.getString("managerServlet.invalidPath", path));
659             return;
660         }
661         String displayPath = path;
662         if( path.equals("/") )
663             path = "";
664 
665         try {
666             Context context = deployer.findDeployedApp(path);
667             if (context == null) {
668                 writer.println(sm.getString("managerServlet.noContext", displayPath));
669                 return;
670             }
671             deployer.stop(path);
672             writer.println(sm.getString("managerServlet.stopped", displayPath));
673         } catch (Throwable t) {
674             getServletContext().log("ManagerServlet.stop[" + displayPath + "]",
675                                     t);
676             writer.println(sm.getString("managerServlet.exception",
677                                         t.toString()));
678         }
679 
680     }
681 
682 
683 }