KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > manager > host > HostManagerServlet


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.manager.host;
20
21
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.io.PrintWriter JavaDoc;
28 import java.util.StringTokenizer JavaDoc;
29
30 import javax.management.MBeanServer JavaDoc;
31 import javax.servlet.ServletException JavaDoc;
32 import javax.servlet.UnavailableException JavaDoc;
33 import javax.servlet.http.HttpServlet JavaDoc;
34 import javax.servlet.http.HttpServletRequest JavaDoc;
35 import javax.servlet.http.HttpServletResponse JavaDoc;
36
37 import org.apache.catalina.Container;
38 import org.apache.catalina.ContainerServlet;
39 import org.apache.catalina.Context;
40 import org.apache.catalina.Engine;
41 import org.apache.catalina.Globals;
42 import org.apache.catalina.Host;
43 import org.apache.catalina.Lifecycle;
44 import org.apache.catalina.Wrapper;
45 import org.apache.catalina.core.StandardHost;
46 import org.apache.catalina.startup.HostConfig;
47 import org.apache.catalina.util.StringManager;
48 import org.apache.tomcat.util.modeler.Registry;
49 import org.apache.catalina.core.ContainerBase;
50
51
52 /**
53  * Servlet that enables remote management of the virtual hosts installed
54  * on the server. Normally, this functionality will be protected by
55  * a security constraint in the web application deployment descriptor.
56  * However, this requirement can be relaxed during testing.
57  * <p>
58  * This servlet examines the value returned by <code>getPathInfo()</code>
59  * and related query parameters to determine what action is being requested.
60  * The following actions and parameters (starting after the servlet path)
61  * are supported:
62  * <ul>
63  * <li><b>/add?name={host-name}&aliases={host-aliases}&manager={manager}</b> -
64  * Create and add a new virtual host. The <code>host-name</code> attribute
65  * indicates the name of the new host. The <code>host-aliases</code>
66  * attribute is a comma separated list of the host alias names.
67  * The <code>manager</code> attribute is a boolean value indicating if the
68  * webapp manager will be installed in the newly created host (optional,
69  * false by default).</li>
70  * <li><b>/remove?name={host-name}</b> - Remove a virtual host.
71  * The <code>host-name</code> attribute indicates the name of the host.
72  * </li>
73  * <li><b>/list</b> - List the virtual hosts installed on the server.
74  * Each host will be listed with the following format
75  * <code>host-name#host-aliases</code>.</li>
76  * <li><b>/start?name={host-name}</b> - Start the virtual host.</li>
77  * <li><b>/stop?name={host-name}</b> - Stop the virtual host.</li>
78  * </ul>
79  * <p>
80  * <b>NOTE</b> - Attempting to stop or remove the host containing
81  * this servlet itself will not succeed. Therefore, this servlet should
82  * generally be deployed in a separate virtual host.
83  * <p>
84  * <b>NOTE</b> - For security reasons, this application will not operate
85  * when accessed via the invoker servlet. You must explicitly map this servlet
86  * with a servlet mapping, and you will always want to protect it with
87  * appropriate security constraints as well.
88  * <p>
89  * The following servlet initialization parameters are recognized:
90  * <ul>
91  * <li><b>debug</b> - The debugging detail level that controls the amount
92  * of information that is logged by this servlet. Default is zero.
93  * </ul>
94  *
95  * @author Craig R. McClanahan
96  * @author Remy Maucherat
97  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
98  */

99
100 public class HostManagerServlet
101     extends HttpServlet JavaDoc implements ContainerServlet {
102
103
104     // ----------------------------------------------------- Instance Variables
105

106
107     /**
108      * Path where context descriptors should be deployed.
109      */

110     protected File JavaDoc configBase = null;
111
112
113     /**
114      * The Context container associated with our web application.
115      */

116     protected Context context = null;
117
118
119     /**
120      * The debugging detail level for this servlet.
121      */

122     protected int debug = 1;
123
124
125     /**
126      * The associated host.
127      */

128     protected Host host = null;
129
130     
131     /**
132      * The associated engine.
133      */

134     protected Engine engine = null;
135
136     
137     /**
138      * MBean server.
139      */

140     protected MBeanServer JavaDoc mBeanServer = null;
141
142
143     /**
144      * The string manager for this package.
145      */

146     protected static StringManager sm =
147         StringManager.getManager(Constants.Package);
148
149
150     /**
151      * The Wrapper container associated with this servlet.
152      */

153     protected Wrapper wrapper = null;
154
155
156     // ----------------------------------------------- ContainerServlet Methods
157

158
159     /**
160      * Return the Wrapper with which we are associated.
161      */

162     public Wrapper getWrapper() {
163
164         return (this.wrapper);
165
166     }
167
168
169     /**
170      * Set the Wrapper with which we are associated.
171      *
172      * @param wrapper The new wrapper
173      */

174     public void setWrapper(Wrapper wrapper) {
175
176         this.wrapper = wrapper;
177         if (wrapper == null) {
178             context = null;
179             host = null;
180             engine = null;
181         } else {
182             context = (Context) wrapper.getParent();
183             host = (Host) context.getParent();
184             engine = (Engine) host.getParent();
185         }
186
187         // Retrieve the MBean server
188
mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
189         
190     }
191
192
193     // --------------------------------------------------------- Public Methods
194

195
196     /**
197      * Finalize this servlet.
198      */

199     public void destroy() {
200
201         ; // No actions necessary
202

203     }
204
205
206     /**
207      * Process a GET request for the specified resource.
208      *
209      * @param request The servlet request we are processing
210      * @param response The servlet response we are creating
211      *
212      * @exception IOException if an input/output error occurs
213      * @exception ServletException if a servlet-specified error occurs
214      */

215     public void doGet(HttpServletRequest JavaDoc request,
216                       HttpServletResponse JavaDoc response)
217         throws IOException JavaDoc, ServletException JavaDoc {
218
219         // Verify that we were not accessed using the invoker servlet
220
if (request.getAttribute(Globals.INVOKED_ATTR) != null)
221             throw new UnavailableException JavaDoc
222                 (sm.getString("hostManagerServlet.cannotInvoke"));
223
224         // Identify the request parameters that we need
225
String JavaDoc command = request.getPathInfo();
226         if (command == null)
227             command = request.getServletPath();
228         String JavaDoc name = request.getParameter("name");
229   
230         // Prepare our output writer to generate the response message
231
response.setContentType("text/plain; charset=" + Constants.CHARSET);
232         PrintWriter JavaDoc writer = response.getWriter();
233
234         // Process the requested command
235
if (command == null) {
236             writer.println(sm.getString("hostManagerServlet.noCommand"));
237         } else if (command.equals("/add")) {
238             add(request, writer, name, false);
239         } else if (command.equals("/remove")) {
240             remove(writer, name);
241         } else if (command.equals("/list")) {
242             list(writer);
243         } else if (command.equals("/start")) {
244             start(writer, name);
245         } else if (command.equals("/stop")) {
246             stop(writer, name);
247         } else {
248             writer.println(sm.getString("hostManagerServlet.unknownCommand",
249                                         command));
250         }
251
252         // Finish up the response
253
writer.flush();
254         writer.close();
255
256     }
257
258
259     /**
260      * Add host with the given parameters.
261      *
262      * @param request The request
263      * @param writer The output writer
264      * @param name The host name
265      * @param htmlMode Flag value
266      */

267     protected void add(HttpServletRequest JavaDoc request, PrintWriter JavaDoc writer, String JavaDoc name, boolean htmlMode ) {
268         String JavaDoc aliases = request.getParameter("aliases");
269         String JavaDoc appBase = request.getParameter("appBase");
270         boolean manager = booleanParameter(request, "manager", false, htmlMode);
271         boolean autoDeploy = booleanParameter(request, "autoDeploy", true, htmlMode);
272         boolean deployOnStartup = booleanParameter(request, "deployOnStartup", true, htmlMode);
273         boolean deployXML = booleanParameter(request, "deployXML", true, htmlMode);
274         boolean unpackWARs = booleanParameter(request, "unpackWARs", true, htmlMode);
275         boolean xmlNamespaceAware = booleanParameter(request, "xmlNamespaceAware", false, htmlMode);
276         boolean xmlValidation = booleanParameter(request, "xmlValidation", false, htmlMode);
277         add(writer, name, aliases, appBase, manager,
278             autoDeploy,
279             deployOnStartup,
280             deployXML,
281             unpackWARs,
282             xmlNamespaceAware,
283             xmlValidation);
284     }
285
286
287     /**
288      * extract boolean value from checkbox with default
289      * @param request
290      * @param parameter
291      * @param theDefault
292      * @param htmlMode
293      * @return
294      */

295     protected boolean booleanParameter(HttpServletRequest JavaDoc request,
296             String JavaDoc parameter, boolean theDefault, boolean htmlMode) {
297         String JavaDoc value = request.getParameter(parameter);
298         boolean booleanValue = theDefault;
299         if (value != null) {
300             if (htmlMode) {
301                 if (value.equals("on")) {
302                     booleanValue = true;
303                 }
304             } else if (theDefault) {
305                 if (value.equals("false")) {
306                     booleanValue = false;
307                 }
308             } else if (value.equals("true")) {
309                 booleanValue = true;
310             }
311         } else if (htmlMode)
312             booleanValue = false;
313         return booleanValue;
314     }
315
316
317     /**
318      * Initialize this servlet.
319      */

320     public void init() throws ServletException JavaDoc {
321
322         // Ensure that our ContainerServlet properties have been set
323
if ((wrapper == null) || (context == null))
324             throw new UnavailableException JavaDoc
325                 (sm.getString("hostManagerServlet.noWrapper"));
326
327         // Verify that we were not accessed using the invoker servlet
328
String JavaDoc servletName = getServletConfig().getServletName();
329         if (servletName == null)
330             servletName = "";
331         if (servletName.startsWith("org.apache.catalina.INVOKER."))
332             throw new UnavailableException JavaDoc
333                 (sm.getString("hostManagerServlet.cannotInvoke"));
334
335         // Set our properties from the initialization parameters
336
String JavaDoc value = null;
337         try {
338             value = getServletConfig().getInitParameter("debug");
339             debug = Integer.parseInt(value);
340         } catch (Throwable JavaDoc t) {
341             ;
342         }
343
344     }
345
346
347
348     // -------------------------------------------------------- Private Methods
349

350
351     /**
352      * Add a host using the specified parameters.
353      *
354      * @param writer Writer to render results to
355      * @param name host name
356      * @param aliases comma separated alias list
357      * @param appBase application base for the host
358      * @param manager should the manager webapp be deployed to the new host ?
359      */

360     protected synchronized void add
361         (PrintWriter JavaDoc writer, String JavaDoc name, String JavaDoc aliases, String JavaDoc appBase,
362          boolean manager,
363          boolean autoDeploy,
364          boolean deployOnStartup,
365          boolean deployXML,
366          boolean unpackWARs,
367          boolean xmlNamespaceAware,
368          boolean xmlValidation) {
369         if (debug >= 1) {
370             log("add: Adding host '" + name + "'");
371         }
372
373         // Validate the requested host name
374
if ((name == null) || name.length() == 0) {
375             writer.println(sm.getString("hostManagerServlet.invalidHostName", name));
376             return;
377         }
378
379         // Check if host already exists
380
if (engine.findChild(name) != null) {
381             writer.println
382                 (sm.getString("hostManagerServlet.alreadyHost", name));
383             return;
384         }
385
386         // Validate and create appBase
387
File JavaDoc appBaseFile = null;
388         if (appBase == null || appBase.length() == 0) {
389             appBase = name;
390         }
391         File JavaDoc file = new File JavaDoc(appBase);
392         if (!file.isAbsolute())
393             file = new File JavaDoc(System.getProperty("catalina.base"), appBase);
394         try {
395             appBaseFile = file.getCanonicalFile();
396         } catch (IOException JavaDoc e) {
397             appBaseFile = file;
398         }
399         if (!appBaseFile.exists()) {
400             appBaseFile.mkdirs();
401         }
402         
403         // Create base for config files
404
File JavaDoc configBaseFile = getConfigBase(name);
405         
406         // Copy manager.xml if requested
407
if (manager) {
408             InputStream JavaDoc is = null;
409             OutputStream JavaDoc os = null;
410             try {
411                 is = getServletContext().getResourceAsStream("/manager.xml");
412                 os = new FileOutputStream JavaDoc(new File JavaDoc(configBaseFile, "manager.xml"));
413                 byte buffer[] = new byte[512];
414                 int len = buffer.length;
415                 while (true) {
416                     len = is.read(buffer);
417                     if (len == -1)
418                         break;
419                     os.write(buffer, 0, len);
420                 }
421             } catch (IOException JavaDoc e) {
422                 writer.println
423                     (sm.getString("hostManagerServlet.managerXml"));
424                 return;
425             } finally {
426                 if (is != null) {
427                     try {
428                         is.close();
429                     } catch (IOException JavaDoc e) {
430                     }
431                 }
432                 if (os != null) {
433                     try {
434                         os.close();
435                     } catch (IOException JavaDoc e) {
436                     }
437                 }
438             }
439         }
440         
441         StandardHost host = new StandardHost();
442         host.setAppBase(appBase);
443         host.setName(name);
444
445         host.addLifecycleListener(new HostConfig());
446
447         // Add host aliases
448
if ((aliases != null) && !("".equals(aliases))) {
449             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(aliases, ", ");
450             while (tok.hasMoreTokens()) {
451                 host.addAlias(tok.nextToken());
452             }
453         }
454         host.setAutoDeploy(autoDeploy);
455         host.setDeployOnStartup(deployOnStartup);
456         host.setDeployXML(deployXML);
457         host.setUnpackWARs(unpackWARs);
458         host.setXmlNamespaceAware(xmlNamespaceAware);
459         host.setXmlValidation(xmlValidation);
460         
461         // Add new host
462
try {
463             engine.addChild(host);
464         } catch (Exception JavaDoc e) {
465             writer.println(sm.getString("hostManagerServlet.exception",
466                                         e.toString()));
467             return;
468         }
469         
470         host = (StandardHost) engine.findChild(name);
471         if (host != null) {
472             writer.println(sm.getString("hostManagerServlet.add", name));
473         } else {
474             // Something failed
475
writer.println(sm.getString("hostManagerServlet.addFailed", name));
476         }
477         
478     }
479
480
481     /**
482      * Remove the specified host.
483      *
484      * @param writer Writer to render results to
485      * @param name host name
486      */

487     protected synchronized void remove(PrintWriter JavaDoc writer, String JavaDoc name) {
488
489         if (debug >= 1) {
490             log("remove: Removing host '" + name + "'");
491         }
492
493         // Validate the requested host name
494
if ((name == null) || name.length() == 0) {
495             writer.println(sm.getString("hostManagerServlet.invalidHostName", name));
496             return;
497         }
498
499         // Check if host exists
500
if (engine.findChild(name) == null) {
501             writer.println
502                 (sm.getString("hostManagerServlet.noHost", name));
503             return;
504         }
505
506         // Prevent removing our own host
507
if (engine.findChild(name) == host) {
508             writer.println
509                 (sm.getString("hostManagerServlet.cannotRemoveOwnHost", name));
510             return;
511         }
512
513         // Remove host
514
// Note that the host will not get physically removed
515
try {
516             Container child = engine.findChild(name);
517             engine.removeChild(child);
518             if ( child instanceof ContainerBase ) ((ContainerBase)child).destroy();
519         } catch (Exception JavaDoc e) {
520             writer.println(sm.getString("hostManagerServlet.exception",
521                                         e.toString()));
522             return;
523         }
524         
525         Host host = (StandardHost) engine.findChild(name);
526         if (host == null) {
527             writer.println(sm.getString("hostManagerServlet.remove", name));
528         } else {
529             // Something failed
530
writer.println(sm.getString("hostManagerServlet.removeFailed", name));
531         }
532         
533     }
534
535
536     /**
537      * Render a list of the currently active Contexts in our virtual host.
538      *
539      * @param writer Writer to render to
540      */

541     protected void list(PrintWriter JavaDoc writer) {
542
543         if (debug >= 1)
544             log("list: Listing hosts for engine '"
545                 + engine.getName() + "'");
546
547         writer.println(sm.getString("hostManagerServlet.listed",
548                                     engine.getName()));
549         Container[] hosts = engine.findChildren();
550         for (int i = 0; i < hosts.length; i++) {
551             Host host = (Host) hosts[i];
552             String JavaDoc name = host.getName();
553             String JavaDoc[] aliases = host.findAliases();
554             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
555             if (aliases.length > 0) {
556                 buf.append(aliases[0]);
557                 for (int j = 1; j < aliases.length; j++) {
558                     buf.append(',').append(aliases[j]);
559                 }
560             }
561             writer.println(sm.getString("hostManagerServlet.listitem",
562                                         name, buf.toString()));
563         }
564     }
565
566
567     /**
568      * Start the host with the specified name.
569      *
570      * @param writer Writer to render to
571      * @param name Host name
572      */

573     protected void start(PrintWriter JavaDoc writer, String JavaDoc name) {
574
575         if (debug >= 1)
576             log("start: Starting host with name '" + name + "'");
577
578         // Validate the requested host name
579
if ((name == null) || name.length() == 0) {
580             writer.println(sm.getString("hostManagerServlet.invalidHostName", name));
581             return;
582         }
583
584         // Check if host exists
585
if (engine.findChild(name) == null) {
586             writer.println
587                 (sm.getString("hostManagerServlet.noHost", name));
588             return;
589         }
590
591         // Prevent starting our own host
592
if (engine.findChild(name) == host) {
593             writer.println
594                 (sm.getString("hostManagerServlet.cannotStartOwnHost", name));
595             return;
596         }
597
598         // Start host
599
try {
600             ((Lifecycle) engine.findChild(name)).start();
601             writer.println
602                 (sm.getString("hostManagerServlet.started", name));
603         } catch (Throwable JavaDoc t) {
604             getServletContext().log
605                 (sm.getString("hostManagerServlet.startFailed", name), t);
606             writer.println
607                 (sm.getString("hostManagerServlet.startFailed", name));
608             writer.println(sm.getString("hostManagerServlet.exception",
609                                         t.toString()));
610             return;
611         }
612         
613     }
614
615
616     /**
617      * Start the host with the specified name.
618      *
619      * @param writer Writer to render to
620      * @param name Host name
621      */

622     protected void stop(PrintWriter JavaDoc writer, String JavaDoc name) {
623
624         if (debug >= 1)
625             log("stop: Stopping host with name '" + name + "'");
626
627         // Validate the requested host name
628
if ((name == null) || name.length() == 0) {
629             writer.println(sm.getString("hostManagerServlet.invalidHostName", name));
630             return;
631         }
632
633         // Check if host exists
634
if (engine.findChild(name) == null) {
635             writer.println
636                 (sm.getString("hostManagerServlet.noHost", name));
637             return;
638         }
639
640         // Prevent starting our own host
641
if (engine.findChild(name) == host) {
642             writer.println
643                 (sm.getString("hostManagerServlet.cannotStopOwnHost", name));
644             return;
645         }
646
647         // Start host
648
try {
649             ((Lifecycle) engine.findChild(name)).stop();
650             writer.println
651                 (sm.getString("hostManagerServlet.stopped", name));
652         } catch (Throwable JavaDoc t) {
653             getServletContext().log
654                 (sm.getString("hostManagerServlet.stopFailed", name), t);
655             writer.println
656                 (sm.getString("hostManagerServlet.stopFailed", name));
657             writer.println(sm.getString("hostManagerServlet.exception",
658                                         t.toString()));
659             return;
660         }
661         
662     }
663
664
665     // -------------------------------------------------------- Support Methods
666

667
668     /**
669      * Get config base.
670      */

671     protected File JavaDoc getConfigBase(String JavaDoc hostName) {
672         File JavaDoc configBase =
673             new File JavaDoc(System.getProperty("catalina.base"), "conf");
674         if (!configBase.exists()) {
675             return null;
676         }
677         if (engine != null) {
678             configBase = new File JavaDoc(configBase, engine.getName());
679         }
680         if (host != null) {
681             configBase = new File JavaDoc(configBase, hostName);
682         }
683         configBase.mkdirs();
684         return configBase;
685     }
686
687
688 }
689
Popular Tags