KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > hostmanager > HostManagerServlet


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

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

104
105     /**
106      * Path where context descriptors should be deployed.
107      */

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

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

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

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

132     protected Engine engine = null;
133
134     
135     /**
136      * MBean server.
137      */

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

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

151     protected Wrapper wrapper = null;
152
153
154     // ----------------------------------------------- ContainerServlet Methods
155

156
157     /**
158      * Return the Wrapper with which we are associated.
159      */

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

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

193
194     /**
195      * Finalize this servlet.
196      */

197     public void destroy() {
198
199         ; // No actions necessary
200

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

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

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

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

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

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

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

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

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

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

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

661
662     /**
663      * Get config base.
664      */

665     protected File JavaDoc getConfigBase(String JavaDoc hostName) {
666         File JavaDoc configBase =
667             new File JavaDoc(System.getProperty("catalina.base"), "conf");
668         if (!configBase.exists()) {
669             return null;
670         }
671         if (engine != null) {
672             configBase = new File JavaDoc(configBase, engine.getName());
673         }
674         if (host != null) {
675             configBase = new File JavaDoc(configBase, hostName);
676         }
677         configBase.mkdirs();
678         return configBase;
679     }
680
681
682 }
683
Popular Tags