1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.catalina.manager;
19
20
21 import java.io.BufferedOutputStream;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.FileNotFoundException;
26 import java.io.InputStream;
27 import java.io.IOException;
28 import java.io.PrintWriter;
29 import java.net.URL;
30 import java.net.MalformedURLException;
31 import java.net.URLConnection;
32 import java.util.Iterator;
33 import java.util.jar.JarEntry;
34 import java.util.jar.JarFile;
35 import javax.naming.Binding;
36 import javax.naming.InitialContext;
37 import javax.naming.NamingEnumeration;
38 import javax.naming.NamingException;
39 import javax.naming.directory.DirContext;
40 import javax.servlet.ServletException;
41 import javax.servlet.ServletInputStream;
42 import javax.servlet.UnavailableException;
43 import javax.servlet.http.HttpServlet;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46 import org.apache.catalina.Container;
47 import org.apache.catalina.ContainerServlet;
48 import org.apache.catalina.Context;
49 import org.apache.catalina.Deployer;
50 import org.apache.catalina.Engine;
51 import org.apache.catalina.Globals;
52 import org.apache.catalina.Host;
53 import org.apache.catalina.Role;
54 import org.apache.catalina.Server;
55 import org.apache.catalina.ServerFactory;
56 import org.apache.catalina.Session;
57 import org.apache.catalina.UserDatabase;
58 import org.apache.catalina.Wrapper;
59 import org.apache.catalina.core.StandardServer;
60 import org.apache.catalina.util.ServerInfo;
61 import org.apache.catalina.util.StringManager;
62 import org.apache.naming.resources.ProxyDirContext;
63 import org.apache.naming.resources.WARDirContext;
64
65 import org.talika.tms.Constants;
66
67
68 /**
69 * Servlet that enables remote management of the web applications installed
70 * within the same virtual host as this web application is. Normally, this
71 * functionality will be protected by a security constraint in the web
72 * application deployment descriptor. However, this requirement can be
73 * relaxed during testing.
74 * <p>
75 * This servlet examines the value returned by <code>getPathInfo()</code>
76 * and related query parameters to determine what action is being requested.
77 * The following actions and parameters (starting after the servlet path)
78 * are supported:
79 * <ul>
80 * <li><b>/deploy?config={config-url}</b> - Install and start a new
81 * web application, based on the contents of the context configuration
82 * file found at the specified URL. The <code>docBase</code> attribute
83 * of the context configuration file is used to locate the actual
84 * WAR or directory containing the application.</li>
85 * <li><b>/deploy?config={config-url}&war={war-url}/</b> - Install and start
86 * a new web application, based on the contents of the context
87 * configuration file found at <code>{config-url}</code>, overriding the
88 * <code>docBase</code> attribute with the contents of the web
89 * application archive found at <code>{war-url}</code>.</li>
90 * <li><b>/deploy?path=/xxx&war={war-url}</b> - Install and start a new
91 * web application attached to context path <code>/xxx</code>, based
92 * on the contents of the web application archive found at the
93 * specified URL.</li>
94 * <li><b>/list</b> - List the context paths of all currently installed web
95 * applications for this virtual host. Each context will be listed with
96 * the following format <code>path:status:sessions</code>.
97 * Where path is the context path. Status is either running or stopped.
98 * Sessions is the number of active Sessions.</li>
99 * <li><b>/reload?path=/xxx</b> - Reload the Java classes and resources for
100 * the application at the specified path.</li>
101 * <li><b>/resources?type=xxxx</b> - Enumerate the available global JNDI
102 * resources, optionally limited to those of the specified type
103 * (fully qualified Java class name), if available.</li>
104 * <li><b>/roles</b> - Enumerate the available security role names and
105 * descriptions from the user database connected to the <code>users</code>
106 * resource reference.
107 * <li><b>/serverinfo</b> - Display system OS and JVM properties.
108 * <li><b>/sessions?path=/xxx</b> - List session information about the web
109 * application attached to context path <code>/xxx</code> for this
110 * virtual host.</li>
111 * <li><b>/start?path=/xxx</b> - Start the web application attached to
112 * context path <code>/xxx</code> for this virtual host.</li>
113 * <li><b>/stop?path=/xxx</b> - Stop the web application attached to
114 * context path <code>/xxx</code> for this virtual host.</li>
115 * <li><b>/undeploy?path=/xxx</b> - Shutdown and remove the web application
116 * attached to context path <code>/xxx</code> for this virtual host,
117 * and remove the underlying WAR file or document base directory.
118 * (<em>NOTE</em> - This is only allowed if the WAR file or document
119 * base is stored in the <code>appBase</code> directory of this host,
120 * typically as a result of being placed there via the <code>/deploy</code>
121 * command.</li>
122 * </ul>
123 * <p>Use <code>path=/</code> for the ROOT context.</p>
124 * <p>The syntax of the URL for a web application archive must conform to one
125 * of the following patterns to be successfully deployed:</p>
126 * <ul>
127 * <li><b>file:/absolute/path/to/a/directory</b> - You can specify the absolute
128 * path of a directory that contains the unpacked version of a web
129 * application. This directory will be attached to the context path you
130 * specify without any changes.</li>
131 * <li><b>jar:file:/absolute/path/to/a/warfile.war!/</b> - You can specify a
132 * URL to a local web application archive file. The syntax must conform to
133 * the rules specified by the <code>JarURLConnection</code> class for a
134 * reference to an entire JAR file.</li>
135 * <li><b>jar:http://hostname:port/path/to/a/warfile.war!/</b> - You can specify
136 * a URL to a remote (HTTP-accessible) web application archive file. The
137 * syntax must conform to the rules specified by the
138 * <code>JarURLConnection</code> class for a reference to an entire
139 * JAR file.</li>
140 * </ul>
141 * <p>
142 * <b>NOTE</b> - Attempting to reload or remove the application containing
143 * this servlet itself will not succeed. Therefore, this servlet should
144 * generally be deployed as a separate web application within the virtual host
145 * to be managed.
146 * <p>
147 * <b>NOTE</b> - For security reasons, this application will not operate
148 * when accessed via the invoker servlet. You must explicitly map this servlet
149 * with a servlet mapping, and you will always want to protect it with
150 * appropriate security constraints as well.
151 * <p>
152 * The following servlet initialization parameters are recognized:
153 * <ul>
154 * <li><b>debug</b> - The debugging detail level that controls the amount
155 * of information that is logged by this servlet. Default is zero.
156 * </ul>
157 *
158 * @author Craig R. McClanahan
159 * @author Remy Maucherat
160 * @author Jose M. Palomar
161 * @version $Revision: 214 $ $Date: 2004-10-24 12:51:42 +0200 (dom 24 de oct de 2004) $
162 *
163 * @todo Test more deploy functions over multiple hosts.
164 */
165
166 public class ManagerXServlet
167 extends HttpServlet implements ContainerServlet {
168
169
170
171
172
173 /**
174 * Path where context descriptors should be deployed.
175 */
176 protected File configBase = null;
177
178
179 /**
180 * The Context container associated with our web application.
181 */
182 protected Context context = null;
183
184
185 /**
186 * The debugging detail level for this servlet.
187 */
188 protected int debug = 1;
189
190
191 /**
192 * Path used to store revisions of webapps.
193 */
194 protected File versioned = null;
195
196
197 /**
198 * Path used to store context descriptors.
199 */
200 protected File contextDescriptors = null;
201
202
203 /**
204 * The Engine container of all our vhosts
205 */
206 protected Engine engine = null;
207
208
209 /**
210 * The global JNDI <code>NamingContext</code> for this server,
211 * if available.
212 */
213 protected javax.naming.Context global = null;
214
215
216 /**
217 * The string manager for this package.
218 */
219 protected static StringManager sm =
220 StringManager.getManager(Constants.Package);
221
222
223 /**
224 * The Wrapper container associated with this servlet.
225 */
226 protected Wrapper wrapper = null;
227
228
229
230
231
232 /**
233 * Return the Wrapper with which we are associated.
234 */
235 public Wrapper getWrapper() {
236
237 return (this.wrapper);
238
239 }
240
241
242 /**
243 * Set the Wrapper with which we are associated.
244 *
245 * @param wrapper The new wrapper
246 */
247 public void setWrapper(Wrapper wrapper) {
248
249 this.wrapper = wrapper;
250 if (wrapper == null) {
251 context = null;
252 engine = null;
253 } else {
254 context = (Context) wrapper.getParent();
255 engine = (Engine) context.getParent().getParent();
256 }
257
258 }
259
260
261
262
263
264 /**
265 * Finalize this servlet.
266 */
267 public void destroy() {
268
269 ;
270
271 }
272
273
274 /**
275 * Process a GET request for the specified resource.
276 *
277 * @param request The servlet request we are processing
278 * @param response The servlet response we are creating
279 *
280 * @exception IOException if an input/output error occurs
281 * @exception ServletException if a servlet-specified error occurs
282 */
283 public void doGet(HttpServletRequest request,
284 HttpServletResponse response)
285 throws IOException, ServletException {
286
287
288 if (request.getAttribute(Globals.INVOKED_ATTR) != null)
289 throw new UnavailableException
290 (sm.getString("managerServlet.cannotInvoke"));
291
292
293 String command = request.getPathInfo();
294 if (command == null)
295 command = request.getServletPath();
296 String vhost = request.getParameter("vhost");
297 String config = request.getParameter("config");
298 String path = request.getParameter("path");
299 String type = request.getParameter("type");
300 String war = request.getParameter("war");
301 String tag = request.getParameter("tag");
302 boolean update = false;
303 if ((request.getParameter("update") != null)
304 && (request.getParameter("update").equals("true"))) {
305 update = true;
306 }
307
308
309 response.setContentType("text/plain; charset=" + Constants.CHARSET);
310 PrintWriter writer = response.getWriter();
311
312
313 if (command == null) {
314 writer.println(sm.getString("managerServlet.noCommand"));
315 } else if (command.equals("/deploy")) {
316 if (war != null) {
317 deploy(writer, vhost, config, path, war, update);
318 } else {
319 deploy(writer, vhost, path, tag);
320 }
321 } else if (command.equals("/install")) {
322
323 deploy(writer, vhost, config, path, war, false);
324 } else if (command.equals("/vhosts")) {
325 vhosts(writer);
326 } else if (command.equals("/list")) {
327 list(writer, vhost);
328 } else if (command.equals("/reload")) {
329 reload(writer, vhost, path);
330 } else if (command.equals("/remove")) {
331
332 remove(writer, vhost, path);
333 } else if (command.equals("/resources")) {
334 resources(writer, type);
335 } else if (command.equals("/roles")) {
336 roles(writer);
337 } else if (command.equals("/save")) {
338 save(writer, vhost, path);
339 } else if (command.equals("/serverinfo")) {
340 serverinfo(writer);
341 } else if (command.equals("/sessions")) {
342 sessions(writer, vhost, path);
343 } else if (command.equals("/start")) {
344 start(writer, vhost, path);
345 } else if (command.equals("/stop")) {
346 stop(writer, vhost, path);
347 } else if (command.equals("/undeploy")) {
348 undeploy(writer, vhost, path);
349 } else {
350 writer.println(sm.getString("managerServlet.unknownCommand",
351 command));
352 }
353
354
355 writer.flush();
356 writer.close();
357
358 }
359
360
361 /**
362 * Process a PUT request for the specified resource.
363 *
364 * @param request The servlet request we are processing
365 * @param response The servlet response we are creating
366 *
367 * @exception IOException if an input/output error occurs
368 * @exception ServletException if a servlet-specified error occurs
369 */
370 public void doPut(HttpServletRequest request,
371 HttpServletResponse response)
372 throws IOException, ServletException {
373
374
375 if (request.getAttribute(Globals.INVOKED_ATTR) != null)
376 throw new UnavailableException
377 (sm.getString("managerServlet.cannotInvoke"));
378
379
380 String command = request.getPathInfo();
381 if (command == null)
382 command = request.getServletPath();
383 String vhost = request.getParameter("vhost");
384 String path = request.getParameter("path");
385 String tag = request.getParameter("tag");
386 boolean update = false;
387 if ((request.getParameter("update") != null)
388 && (request.getParameter("update").equals("true"))) {
389 update = true;
390 }
391
392
393 response.setContentType("text/plain;charset="+Constants.CHARSET);
394 PrintWriter writer = response.getWriter();
395
396
397 if (command == null) {
398 writer.println(sm.getString("managerServlet.noCommand"));
399 } else if (command.equals("/deploy")) {
400 deploy(writer, vhost, path, tag, update, request);
401 } else {
402 writer.println(sm.getString("managerServlet.unknownCommand",
403 command));
404 }
405
406
407 writer.flush();
408 writer.close();
409
410 }
411
412
413 /**
414 * Initialize this servlet.
415 */
416 public void init() throws ServletException {
417
418
419 if ((wrapper == null) || (context == null))
420 throw new UnavailableException
421 (sm.getString("managerServlet.noWrapper"));
422
423
424 String servletName = getServletConfig().getServletName();
425 if (servletName == null)
426 servletName = "";
427 if (servletName.startsWith("org.apache.catalina.INVOKER."))
428 throw new UnavailableException
429 (sm.getString("managerServlet.cannotInvoke"));
430
431
432 String value = null;
433 try {
434 value = getServletConfig().getInitParameter("debug");
435 debug = Integer.parseInt(value);
436 } catch (Throwable t) {
437 ;
438 }
439
440
441 Server server = ServerFactory.getServer();
442 if ((server != null) && (server instanceof StandardServer)) {
443 global = ((StandardServer) server).getGlobalNamingContext();
444 }
445
446
447 versioned = (File) getServletContext().getAttribute
448 ("javax.servlet.context.tempdir");
449
450 configBase = new File(System.getProperty("catalina.base"), "conf");
451 Container container = context;
452 Container host = null;
453 Container engine = null;
454 while (container != null) {
455 if (container instanceof Host)
456 host = container;
457 if (container instanceof Engine)
458 engine = container;
459 container = container.getParent();
460 }
461 if (engine != null) {
462 configBase = new File(configBase, engine.getName());
463 }
464 if (host != null) {
465 configBase = new File(configBase, host.getName());
466 }
467
468
469
470 if (debug >= 1) {
471 log("init: Associated with Engine '" +
472 engine.getName() + "'");
473 if (global != null) {
474 log("init: Global resources are available");
475 }
476 }
477
478 }
479
480
481
482
483
484
485 /**
486 * Render a list of the currently active vhosts.
487 *
488 * @param writer Writer to render to
489 */
490 protected void vhosts(PrintWriter writer) {
491
492 if (debug >= 1)
493 log("list: Listing virtual hosts for engine '" +
494 engine.getName() + "'");
495
496 writer.println(sm.getString("managerServlet.vhosts",
497 engine.getName()));
498
499 Container hosts[] = engine.findChildren();
500 for (int i = 0; i < hosts.length; i++) {
501 writer.println(sm.getString("managerServlet.hostitem",
502 hosts[i].getName()));
503 }
504
505 }
506
507 /**
508 * Store server configuration.
509 *
510 * @param vhost Virtual host to be listed
511 * @param path Optional context path to save
512 */
513 protected synchronized void save(PrintWriter writer, String vhost, String path) {
514
515 Server server = ServerFactory.getServer();
516
517 if (!(server instanceof StandardServer)) {
518 writer.println(sm.getString("managerServlet.saveFail", server));
519 return;
520 }
521
522 if(vhost == null || vhost.length() == 0) {
523 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
524 return;
525 }
526
527 Deployer deployer = (Deployer) engine.findChild(vhost);
528 if (deployer == null) {
529 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
530 return;
531 }
532
533 if ((path == null) || path.length() == 0 || !path.startsWith("/")) {
534 try {
535 ((StandardServer) server).storeConfig();
536 writer.println(sm.getString("managerServlet.saved"));
537 } catch (Exception e) {
538 log("managerServlet.storeConfig", e);
539 writer.println(sm.getString("managerServlet.exception",
540 e.toString()));
541 return;
542 }
543 } else {
544 String contextPath = path;
545 if (path.equals("/")) {
546 contextPath = "";
547 }
548 Context context = deployer.findDeployedApp(contextPath);
549 if (context == null) {
550 writer.println(sm.getString("managerServlet.noContext", path));
551 return;
552 }
553 try {
554 ((StandardServer) server).storeContext(context);
555 writer.println(sm.getString("managerServlet.savedContext",
556 path));
557 } catch (Exception e) {
558 log("managerServlet.save[" + path + "]", e);
559 writer.println(sm.getString("managerServlet.exception",
560 e.toString()));
561 return;
562 }
563 }
564
565 }
566
567
568 /**
569 * Deploy a web application archive (included in the current request)
570 * at the specified context path.
571 *
572 * @param writer Writer to render results to
573 * @param vhost Virtual host to be listed
574 * @param path Context path of the application to be installed
575 * @param tag Tag to be associated with the webapp
576 * @param request Servlet request we are processing
577 */
578 protected synchronized void deploy
579 (PrintWriter writer, String vhost, String path,
580 String tag, boolean update, HttpServletRequest request) {
581
582 if (debug >= 1) {
583 log("deploy: Deploying web application at '" + vhost + ":" + path + "'");
584 }
585
586 if(vhost == null || vhost.length() == 0) {
587 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
588 return;
589 }
590
591 Deployer deployer = (Deployer) engine.findChild(vhost);
592 if (deployer == null) {
593 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
594 return;
595 }
596
597
598 if ((path == null) || path.length() == 0 || !path.startsWith("/")) {
599 writer.println(sm.getString("managerServlet.invalidPath", path));
600 return;
601 }
602 String displayPath = path;
603 if( path.equals("/") )
604 path = "";
605 String basename = getConfigFile(path);
606
607
608 Context context = deployer.findDeployedApp(path);
609 if (update) {
610 if (context != null) {
611 undeploy(writer, vhost, displayPath);
612 }
613 context = deployer.findDeployedApp(path);
614 }
615 if (context != null) {
616 writer.println
617 (sm.getString("managerServlet.alreadyContext",
618 displayPath));
619 return;
620 }
621
622
623 File deployedPath = getDeployed(context);
624 if (tag != null) {
625 deployedPath = new File(versioned, tag);
626 deployedPath.mkdirs();
627 }
628
629
630 File localWar = new File(deployedPath, basename + ".war");
631 if (debug >= 2) {
632 log("Uploading WAR file to " + localWar);
633 }
634 try {
635 uploadWar(request, localWar);
636 } catch (IOException e) {
637 log("managerServlet.upload[" + displayPath + "]", e);
638 writer.println(sm.getString("managerServlet.exception",
639 e.toString()));
640 return;
641 }
642
643
644 if (tag != null) {
645 deployedPath = getDeployed(context);
646 File localWarCopy = new File(deployedPath, basename + ".war");
647 copy(localWar, localWarCopy);
648 localWar = localWarCopy;
649 }
650
651 String war = null;
652 try {
653 URL url = localWar.toURL();
654 war = url.toString();
655 war = "jar:" + war + "!/";
656 } catch(MalformedURLException e) {
657 log("managerServlet.badUrl[" + displayPath + "]", e);
658 writer.println(sm.getString("managerServlet.exception",
659 e.toString()));
660 return;
661 }
662
663
664 File localXml = new File(configBase, basename + ".xml");
665 if (debug >= 2) {
666 log("Extracting XML file to " + localXml);
667 }
668 try {
669 extractXml(localWar, localXml);
670 } catch (IOException e) {
671 log("managerServlet.extract[" + displayPath + "]", e);
672 writer.println(sm.getString("managerServlet.exception",
673 e.toString()));
674 return;
675 }
676 String config = null;
677 try {
678 if (localXml.exists()) {
679 URL url = localXml.toURL();
680 config = url.toString();
681 }
682 } catch (MalformedURLException e) {
683 log("managerServlet.badUrl[" + displayPath + "]", e);
684 writer.println(sm.getString("managerServlet.exception",
685 e.toString()));
686 return;
687 }
688
689
690 deploy(writer, vhost, config, path, war, update);
691
692 }
693
694
695 /**
696 * Install an application for the specified path from the specified
697 * web application archive.
698 *
699 * @param writer Writer to render results to
700 * @param vhost Virtual host to be listed
701 * @param tag Revision tag to deploy from
702 * @param path Context path of the application to be installed
703 */
704 protected void deploy(PrintWriter writer, String vhost, String path, String tag) {
705
706 if(vhost == null || vhost.length() == 0) {
707 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
708 return;
709 }
710
711 Deployer deployer = (Deployer) engine.findChild(vhost);
712 if (deployer == null) {
713 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
714 return;
715 }
716
717
718 if ((path == null) || path.length() == 0 || !path.startsWith("/")) {
719 writer.println(sm.getString("managerServlet.invalidPath", path));
720 return;
721 }
722 String displayPath = path;
723 if( path.equals("/") )
724 path = "";
725 String basename = getConfigFile(path);
726
727
728 File deployedPath = versioned;
729 if (tag != null) {
730 deployedPath = new File(deployedPath, tag);
731 }
732
733
734 File localWar = new File(deployedPath, basename + ".war");
735
736 File localXml = new File(configBase, basename + ".xml");
737
738
739 Context context = deployer.findDeployedApp(path);
740 if (context != null) {
741 undeploy(writer, vhost, displayPath);
742 }
743
744
745 if (tag != null) {
746 File deployed = getDeployed(context);
747 File localWarCopy = new File(deployed, basename + ".war");
748 copy(localWar, localWarCopy);
749 try {
750 extractXml(localWar, localXml);
751 } catch (IOException e) {
752 log("managerServlet.extract[" + displayPath + "]", e);
753 writer.println(sm.getString("managerServlet.exception",
754 e.toString()));
755 return;
756 }
757 localWar = localWarCopy;
758 }
759
760
761 String war = null;
762 try {
763 URL url = localWar.toURL();
764 war = url.toString();
765 war = "jar:" + war + "!/";
766 } catch(MalformedURLException e) {
767 log("managerServlet.badUrl[" + displayPath + "]", e);
768 writer.println(sm.getString("managerServlet.exception",
769 e.toString()));
770 return;
771 }
772 String config = null;
773 try {
774 if (localXml.exists()) {
775 URL url = localXml.toURL();
776 config = url.toString();
777 }
778 } catch (MalformedURLException e) {
779 log("managerServlet.badUrl[" + displayPath + "]", e);
780 writer.println(sm.getString("managerServlet.exception",
781 e.toString()));
782 return;
783 }
784
785
786 deploy(writer, vhost, config, path, war, false);
787
788 }
789
790
791 /**
792 * Install an application for the specified path from the specified
793 * web application archive.
794 *
795 * @param writer Writer to render results to
796 * @param vhost Virtual host to be listed
797 * @param config URL of the context configuration file to be installed
798 * @param path Context path of the application to be installed
799 * @param war URL of the web application archive to be installed
800 * @param update true to override any existing webapp on the path
801 */
802 protected void deploy(PrintWriter writer, String vhost, String config,
803 String path, String war, boolean update) {
804
805 if(vhost == null || vhost.length() == 0) {
806 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
807 return;
808 }
809
810 Deployer deployer = (Deployer) engine.findChild(vhost);
811 if (deployer == null) {
812 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
813 return;
814 }
815
816 if (war != null && war.length() == 0) {
817 war = null;
818 }
819
820 if (debug >= 1) {
821 if (config != null && config.length() > 0) {
822 if (war != null) {
823 log("install: Installing context configuration at '" +
824 config + "' from '" + war + "'");
825 } else {
826 log("install: Installing context configuration at '" +
827 config + "'");
828 }
829 } else {
830 if (path != null && path.length() > 0) {
831 log("install: Installing web application at '" + path +
832 "' from '" + war + "'");
833 } else {
834 log("install: Installing web application from '" + war + "'");
835 }
836 }
837 }
838
839
840 if (war != null && war.indexOf('/') < 0 ) {
841
842 String appBase = null;
843 File appBaseDir = null;
844 if (context.getParent() instanceof Host) {
845 appBase = ((Host) context.getParent()).getAppBase();
846 appBaseDir = new File(appBase);
847 if (!appBaseDir.isAbsolute()) {
848 appBaseDir = new File(System.getProperty("catalina.base"),
849 appBase);
850 }
851 File file = new File(appBaseDir, war);
852 try {
853 URL url = file.toURL();
854 war = url.toString();
855 if (war.toLowerCase().endsWith(".war")) {
856 war = "jar:" + war + "!/";
857 }
858 } catch(MalformedURLException e) {
859 ;
860 }
861 }
862 }
863
864 if (config != null && config.length() > 0) {
865
866 if ((war != null) &&
867 (!war.startsWith("file:") && !war.startsWith("jar:"))) {
868 writer.println(sm.getString("managerServlet.invalidWar", war));
869 return;
870 }
871
872 try {
873 if (war == null) {
874 deployer.install(new URL(config), null);
875 } else {
876 deployer.install(new URL(config), new URL(war));
877 }
878 writer.println(sm.getString("managerServlet.configured",
879 config));
880 } catch (Throwable t) {
881 log("ManagerServlet.configure[" + config + "]", t);
882 writer.println(sm.getString("managerServlet.exception",
883 t.toString()));
884 return;
885 }
886
887 } else {
888
889 if ((war == null) ||
890 (!war.startsWith("file:") && !war.startsWith("jar:"))) {
891 writer.println(sm.getString("managerServlet.invalidWar", war));
892 return;
893 }
894
895 if (path == null || path.length() == 0) {
896 if (deployer.isDeployXML()) {
897
898 URL contextXml = null;
899 InputStream stream = null;
900 try {
901 String contextWar = war;
902 if (war.startsWith("file:")) {
903 if (war.endsWith(".war")) {
904 contextWar = "jar:" + war + "!/";
905 } else {
906 contextWar = war + '/';
907 }
908 }
909 contextXml = new URL(contextWar +
910 "META-INF/context.xml");
911 URLConnection jarUrlConnection=contextXml.openConnection();
912 jarUrlConnection.setUseCaches(false);
913 stream = jarUrlConnection.getInputStream();;
914
915
916 deployer.install(new URL(contextWar));
917 return;
918 } catch (FileNotFoundException fnfe) {
919
920 } catch (Throwable t) {
921 log("ManagerServlet.configure[" + contextXml + "]", t);
922 writer.println(sm.getString("managerServlet.exception",
923 t.toString()));
924 return;
925 } finally {
926 if (stream != null) {
927 try {
928 stream.close();
929 } catch (Throwable t) {
930
931 }
932 }
933
934 }
935 }
936
937 int end = war.length();
938 String filename = war.toLowerCase();
939 if (filename.endsWith("!/")) {
940 filename = filename.substring(0,filename.length()-2);
941 end -= 2;
942 }
943 if (filename.endsWith(".war")) {
944 filename = filename.substring(0,filename.length()-4);
945 end -= 4;
946 }
947 if (filename.endsWith("/")) {
948 filename = filename.substring(0,filename.length()-1);
949 end--;
950 }
951 int beg = filename.lastIndexOf('/') + 1;
952 if (beg < 0 || end < 0 || beg >= end) {
953 writer.println(sm.getString("managerServlet.invalidWar", war));
954 return;
955 }
956 path = "/" + war.substring(beg, end);
957 if (path.equals("/ROOT")) {
958 path = "/";
959 }
960 }
961
962 if (path == null || path.length() == 0 || !path.startsWith("/")) {
963 writer.println(sm.getString("managerServlet.invalidPath",
964 path));
965 return;
966 }
967 String displayPath = path;
968 if("/".equals(path)) {
969 path = "";
970 }
971
972
973 Context context = deployer.findDeployedApp(path);
974 if (update) {
975 if (context != null) {
976 undeploy(writer, vhost, displayPath);
977 }
978 context = deployer.findDeployedApp(path);
979 }
980 if (context != null) {
981 writer.println
982 (sm.getString("managerServlet.alreadyContext",
983 displayPath));
984 return;
985 }
986
987 try {
988 deployer.install(path, new URL(war));
989 writer.println(sm.getString("managerServlet.deployed",
990 displayPath));
991 } catch (Throwable t) {
992 log("ManagerServlet.install[" + displayPath + "]", t);
993 writer.println(sm.getString("managerServlet.exception",
994 t.toString()));
995 }
996
997 }
998
999 }
1000
1001
1002 /**
1003 * Render a list of the currently active Contexts in our virtual host.
1004 *
1005 * @param writer Writer to render to
1006 * @param vhost Virtual host to be listed
1007 */
1008 protected void list(PrintWriter writer, String vhost) {
1009
1010 if (debug >= 1)
1011 log("list: Listing contexts for virtual host '" +
1012 vhost + "'");
1013
1014 if(vhost == null || vhost.length() == 0) {
1015 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1016 return;
1017 }
1018
1019 Deployer deployer = (Deployer) engine.findChild(vhost);
1020 if (deployer == null) {
1021 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1022 return;
1023 }
1024
1025 writer.println(sm.getString("managerServlet.listed",
1026 deployer.getName()));
1027 String contextPaths[] = deployer.findDeployedApps();
1028 for (int i = 0; i < contextPaths.length; i++) {
1029 Context context = deployer.findDeployedApp(contextPaths[i]);
1030 String displayPath = contextPaths[i];
1031 if( displayPath.equals("") )
1032 displayPath = "/";
1033 if (context != null ) {
1034 if (context.getAvailable()) {
1035 writer.println(sm.getString("managerServlet.listitem",
1036 displayPath,
1037 "running",
1038 "" + context.getManager().findSessions().length,
1039 context.getDocBase()));
1040 } else {
1041 writer.println(sm.getString("managerServlet.listitem",
1042 displayPath,
1043 "stopped",
1044 "0",
1045 context.getDocBase()));
1046 }
1047 }
1048 }
1049 }
1050
1051
1052 /**
1053 * Reload the web application at the specified context path.
1054 *
1055 * @param writer Writer to render to
1056 * @param vhost Virtual host to be listed
1057 * @param path Context path of the application to be restarted
1058 */
1059 protected void reload(PrintWriter writer, String vhost, String path) {
1060
1061 if (debug >= 1)
1062 log("restart: Reloading web application at '" + vhost + ":" + path + "'");
1063
1064 if(vhost == null || vhost.length() == 0) {
1065 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1066 return;
1067 }
1068
1069 Deployer deployer = (Deployer) engine.findChild(vhost);
1070 if (deployer == null) {
1071 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1072 return;
1073 }
1074
1075 if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
1076 writer.println(sm.getString("managerServlet.invalidPath", path));
1077 return;
1078 }
1079 String displayPath = path;
1080 if( path.equals("/") )
1081 path = "";
1082
1083 try {
1084 Context context = deployer.findDeployedApp(path);
1085 if (context == null) {
1086 writer.println(sm.getString
1087 ("managerServlet.noContext", displayPath));
1088 return;
1089 }
1090 DirContext resources = context.getResources();
1091 if (resources instanceof ProxyDirContext) {
1092 resources = ((ProxyDirContext) resources).getDirContext();
1093 }
1094 if (resources instanceof WARDirContext) {
1095 writer.println(sm.getString
1096 ("managerServlet.noReload", displayPath));
1097 return;
1098 }
1099
1100 if (context.getPath().equals(this.context.getPath())) {
1101 writer.println(sm.getString("managerServlet.noSelf"));
1102 return;
1103 }
1104 context.reload();
1105 writer.println
1106 (sm.getString("managerServlet.reloaded", displayPath));
1107 } catch (Throwable t) {
1108 log("ManagerServlet.reload[" + displayPath + "]", t);
1109 writer.println(sm.getString("managerServlet.exception",
1110 t.toString()));
1111 }
1112
1113 }
1114
1115
1116 /**
1117 * Remove the web application at the specified context path.
1118 *
1119 * @param writer Writer to render to
1120 * @param vhost Virtual host to be listed
1121 * @param path Context path of the application to be removed
1122 * @deprecated Replaced by undeploy
1123 */
1124 protected void remove(PrintWriter writer, String vhost, String path) {
1125
1126 if (debug >= 1)
1127 log("remove: Removing web application at '" + vhost + ":" + path + "'");
1128
1129 if(vhost == null || vhost.length() == 0) {
1130 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1131 return;
1132 }
1133
1134 Deployer deployer = (Deployer) engine.findChild(vhost);
1135 if (deployer == null) {
1136 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1137 return;
1138 }
1139
1140 if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
1141 writer.println(sm.getString("managerServlet.invalidPath", path));
1142 return;
1143 }
1144 String displayPath = path;
1145 if( path.equals("/") )
1146 path = "";
1147
1148 try {
1149 Context context = deployer.findDeployedApp(path);
1150 if (context == null) {
1151 writer.println(sm.getString("managerServlet.noContext", displayPath));
1152 return;
1153 }
1154
1155 if (context.getPath().equals(this.context.getPath())) {
1156 writer.println(sm.getString("managerServlet.noSelf"));
1157 return;
1158 }
1159 deployer.remove(path,true);
1160 writer.println(sm.getString("managerServlet.undeployed", displayPath));
1161 } catch (Throwable t) {
1162 log("ManagerServlet.remove[" + displayPath + "]", t);
1163 writer.println(sm.getString("managerServlet.exception",
1164 t.toString()));
1165 }
1166
1167 }
1168
1169
1170 /**
1171 * Render a list of available global JNDI resources.
1172 *
1173 * @param type Fully qualified class name of the resource type of interest,
1174 * or <code>null</code> to list resources of all types
1175 */
1176 protected void resources(PrintWriter writer, String type) {
1177
1178 if (debug >= 1) {
1179 if (type != null) {
1180 log("resources: Listing resources of type " + type);
1181 } else {
1182 log("resources: Listing resources of all types");
1183 }
1184 }
1185
1186
1187 if (global == null) {
1188 writer.println(sm.getString("managerServlet.noGlobal"));
1189 return;
1190 }
1191
1192
1193 if (type != null) {
1194 writer.println(sm.getString("managerServlet.resourcesType",
1195 type));
1196 } else {
1197 writer.println(sm.getString("managerServlet.resourcesAll"));
1198 }
1199
1200 Class clazz = null;
1201 try {
1202 if (type != null) {
1203 clazz = Class.forName(type);
1204 }
1205 } catch (Throwable t) {
1206 log("ManagerServlet.resources[" + type + "]", t);
1207 writer.println(sm.getString("managerServlet.exception",
1208 t.toString()));
1209 return;
1210 }
1211
1212 printResources(writer, "", global, type, clazz);
1213
1214 }
1215
1216
1217 /**
1218 * List the resources of the given context.
1219 */
1220 protected void printResources(PrintWriter writer, String prefix,
1221 javax.naming.Context namingContext,
1222 String type, Class clazz) {
1223
1224 try {
1225 NamingEnumeration items = namingContext.listBindings("");
1226 while (items.hasMore()) {
1227 Binding item = (Binding) items.next();
1228 if (item.getObject() instanceof javax.naming.Context) {
1229 printResources
1230 (writer, prefix + item.getName() + "/",
1231 (javax.naming.Context) item.getObject(), type, clazz);
1232 } else {
1233 if ((clazz != null) &&
1234 (!(clazz.isInstance(item.getObject())))) {
1235 continue;
1236 }
1237 writer.print(prefix + item.getName());
1238 writer.print(':');
1239 writer.print(item.getClassName());
1240
1241 writer.println();
1242 }
1243 }
1244 } catch (Throwable t) {
1245 log("ManagerServlet.resources[" + type + "]", t);
1246 writer.println(sm.getString("managerServlet.exception",
1247 t.toString()));
1248 }
1249
1250 }
1251
1252
1253 /**
1254 * Render a list of security role names (and corresponding descriptions)
1255 * from the <code>org.apache.catalina.UserDatabase</code> resource that is
1256 * connected to the <code>users</code> resource reference. Typically, this
1257 * will be the global user database, but can be adjusted if you have
1258 * different user databases for different virtual hosts.
1259 *
1260 * @param writer Writer to render to
1261 */
1262 protected void roles(PrintWriter writer) {
1263
1264 if (debug >= 1) {
1265 log("roles: List security roles from user database");
1266 }
1267
1268
1269 UserDatabase database = null;
1270 try {
1271 InitialContext ic = new InitialContext();
1272 database = (UserDatabase) ic.lookup("java:comp/env/users");
1273 } catch (NamingException e) {
1274 writer.println(sm.getString("managerServlet.userDatabaseError"));
1275 log("java:comp/env/users", e);
1276 return;
1277 }
1278 if (database == null) {
1279 writer.println(sm.getString("managerServlet.userDatabaseMissing"));
1280 return;
1281 }
1282
1283
1284 writer.println(sm.getString("managerServlet.rolesList"));
1285 Iterator roles = database.getRoles();
1286 if (roles != null) {
1287 while (roles.hasNext()) {
1288 Role role = (Role) roles.next();
1289 writer.print(role.getRolename());
1290 writer.print(':');
1291 if (role.getDescription() != null) {
1292 writer.print(role.getDescription());
1293 }
1294 writer.println();
1295 }
1296 }
1297
1298
1299 }
1300
1301
1302 /**
1303 * Writes System OS and JVM properties.
1304 * @param writer Writer to render to
1305 */
1306 protected void serverinfo(PrintWriter writer) {
1307 if (debug >= 1)
1308 log("serverinfo");
1309 try {
1310 StringBuffer props = new StringBuffer();
1311 props.append("OK - Server info");
1312 props.append("\nTomcat Version: ");
1313 props.append(ServerInfo.getServerInfo());
1314 props.append("\nOS Name: ");
1315 props.append(System.getProperty("os.name"));
1316 props.append("\nOS Version: ");
1317 props.append(System.getProperty("os.version"));
1318 props.append("\nOS Architecture: ");
1319 props.append(System.getProperty("os.arch"));
1320 props.append("\nJVM Version: ");
1321 props.append(System.getProperty("java.runtime.version"));
1322 props.append("\nJVM Vendor: ");
1323 props.append(System.getProperty("java.vm.vendor"));
1324 writer.println(props.toString());
1325 } catch (Throwable t) {
1326 getServletContext().log("ManagerServlet.serverinfo",t);
1327 writer.println(sm.getString("managerServlet.exception",
1328 t.toString()));
1329 }
1330 }
1331
1332 /**
1333 * Session information for the web application at the specified context path.
1334 * Displays a profile of session MaxInactiveInterval timeouts listing number
1335 * of sessions for each 10 minute timeout interval up to 10 hours.
1336 *
1337 * @param writer Writer to render to
1338 * @param vhost Virtual host to be listed
1339 * @param path Context path of the application to list session information for
1340 */
1341 protected void sessions(PrintWriter writer, String vhost, String path) {
1342
1343 if (debug >= 1)
1344 log("sessions: Session information for web application at '" + vhost + ":" + path + "'");
1345
1346 if(vhost == null || vhost.length() == 0) {
1347 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1348 return;
1349 }
1350
1351 Deployer deployer = (Deployer) engine.findChild(vhost);
1352 if (deployer == null) {
1353 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1354 return;
1355 }
1356
1357 if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
1358 writer.println(sm.getString("managerServlet.invalidPath", path));
1359 return;
1360 }
1361 String displayPath = path;
1362 if( path.equals("/") )
1363 path = "";
1364 try {
1365 Context context = deployer.findDeployedApp(path);
1366 if (context == null) {
1367 writer.println(sm.getString("managerServlet.noContext", displayPath));
1368 return;
1369 }
1370 writer.println(sm.getString("managerServlet.sessions", displayPath));
1371 writer.println(sm.getString("managerServlet.sessiondefaultmax",
1372 "" + context.getManager().getMaxInactiveInterval()/60));
1373 Session [] sessions = context.getManager().findSessions();
1374 int [] timeout = new int[60];
1375 int notimeout = 0;
1376 for (int i = 0; i < sessions.length; i++) {
1377 int time = sessions[i].getMaxInactiveInterval()/(10*60);
1378 if (time < 0)
1379 notimeout++;
1380 else if (time >= timeout.length)
1381 timeout[timeout.length-1]++;
1382 else
1383 timeout[time]++;
1384 }
1385 if (timeout[0] > 0)
1386 writer.println(sm.getString("managerServlet.sessiontimeout",
1387 "<10", "" + timeout[0]));
1388 for (int i = 1; i < timeout.length-1; i++) {
1389 if (timeout[i] > 0)
1390 writer.println(sm.getString("managerServlet.sessiontimeout",
1391 "" + (i)*10 + " - <" + (i+1)*10,
1392 "" + timeout[i]));
1393 }
1394 if (timeout[timeout.length-1] > 0)
1395 writer.println(sm.getString("managerServlet.sessiontimeout",
1396 ">=" + timeout.length*10,
1397 "" + timeout[timeout.length-1]));
1398 if (notimeout > 0)
1399 writer.println(sm.getString("managerServlet.sessiontimeout",
1400 "unlimited","" + notimeout));
1401 } catch (Throwable t) {
1402 log("ManagerServlet.sessions[" + displayPath + "]", t);
1403 writer.println(sm.getString("managerServlet.exception",
1404 t.toString()));
1405 }
1406
1407 }
1408
1409
1410 /**
1411 * Start the web application at the specified context path.
1412 *
1413 * @param writer Writer to render to
1414 * @param vhost Virtual host to be listed
1415 * @param path Context path of the application to be started
1416 */
1417 protected void start(PrintWriter writer, String vhost, String path) {
1418
1419 if (debug >= 1)
1420 log("start: Starting web application at '" + vhost + ":" + path + "'");
1421
1422 if(vhost == null || vhost.length() == 0) {
1423 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1424 return;
1425 }
1426
1427 Deployer deployer = (Deployer) engine.findChild(vhost);
1428 if (deployer == null) {
1429 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1430 return;
1431 }
1432
1433 if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
1434 writer.println(sm.getString("managerServlet.invalidPath", path));
1435 return;
1436 }
1437 String displayPath = path;
1438 if( path.equals("/") )
1439 path = "";
1440
1441 try {
1442 Context context = deployer.findDeployedApp(path);
1443 if (context == null) {
1444 writer.println(sm.getString("managerServlet.noContext",
1445 displayPath));
1446 return;
1447 }
1448 deployer.start(path);
1449 if (context.getAvailable())
1450 writer.println
1451 (sm.getString("managerServlet.started", displayPath));
1452 else
1453 writer.println
1454 (sm.getString("managerServlet.startFailed", displayPath));
1455 } catch (Throwable t) {
1456 getServletContext().log
1457 (sm.getString("managerServlet.startFailed", displayPath), t);
1458 writer.println
1459 (sm.getString("managerServlet.startFailed", displayPath));
1460 writer.println(sm.getString("managerServlet.exception",
1461 t.toString()));
1462 }
1463
1464 }
1465
1466
1467 /**
1468 * Stop the web application at the specified context path.
1469 *
1470 * @param writer Writer to render to
1471 * @param vhost Virtual host to be listed
1472 * @param path Context path of the application to be stopped
1473 */
1474 protected void stop(PrintWriter writer, String vhost, String path) {
1475
1476 if (debug >= 1)
1477 log("stop: Stopping web application at '" + vhost + ":" + path + "'");
1478
1479 if(vhost == null || vhost.length() == 0) {
1480 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1481 return;
1482 }
1483
1484 Deployer deployer = (Deployer) engine.findChild(vhost);
1485 if (deployer == null) {
1486 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1487 return;
1488 }
1489
1490 if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
1491 writer.println(sm.getString("managerServlet.invalidPath", path));
1492 return;
1493 }
1494 String displayPath = path;
1495 if( path.equals("/") )
1496 path = "";
1497
1498 try {
1499 Context context = deployer.findDeployedApp(path);
1500 if (context == null) {
1501 writer.println(sm.getString("managerServlet.noContext",
1502 displayPath));
1503 return;
1504 }
1505
1506 if (context.getPath().equals(this.context.getPath())) {
1507 writer.println(sm.getString("managerServlet.noSelf"));
1508 return;
1509 }
1510 deployer.stop(path);
1511 writer.println(sm.getString("managerServlet.stopped", displayPath));
1512 } catch (Throwable t) {
1513 log("ManagerServlet.stop[" + displayPath + "]", t);
1514 writer.println(sm.getString("managerServlet.exception",
1515 t.toString()));
1516 }
1517
1518 }
1519
1520
1521 /**
1522 * Undeploy the web application at the specified context path.
1523 *
1524 * @param writer Writer to render to
1525 * @param vhost Virtual host to be listed
1526 * @param path Context path of the application to be removed
1527 */
1528 protected void undeploy(PrintWriter writer, String vhost, String path) {
1529
1530 if (debug >= 1)
1531 log("undeploy: Undeploying web application at '" + vhost + ":" + path + "'");
1532
1533 if(vhost == null || vhost.length() == 0) {
1534 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1535 return;
1536 }
1537
1538 Deployer deployer = (Deployer) engine.findChild(vhost);
1539 if (deployer == null) {
1540 writer.println(sm.getString("managerServlet.invalidVirtualHost", vhost));
1541 return;
1542 }
1543
1544 if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
1545 writer.println(sm.getString("managerServlet.invalidPath", path));
1546 return;
1547 }
1548 String displayPath = path;
1549 if( path.equals("/") )
1550 path = "";
1551
1552 try {
1553
1554
1555 Context context = deployer.findDeployedApp(path);
1556 if (context == null) {
1557 writer.println(sm.getString("managerServlet.noContext",
1558 displayPath));
1559 return;
1560 }
1561
1562
1563 String appBase = null;
1564 File appBaseDir = null;
1565 if (context.getParent() instanceof Host) {
1566 appBase = ((Host) context.getParent()).getAppBase();
1567 appBaseDir = new File(appBase);
1568 if (!appBaseDir.isAbsolute()) {
1569 appBaseDir = new File(System.getProperty("catalina.base"),
1570 appBase);
1571 }
1572 }
1573
1574
1575 File deployed = getDeployed(context);
1576 String deployedPath = deployed.getCanonicalPath();
1577 String docBase = context.getDocBase();
1578 File docBaseDir = new File(docBase);
1579 if (!docBaseDir.isAbsolute()) {
1580 docBaseDir = new File(appBaseDir, docBase);
1581 }
1582 String docBasePath = docBaseDir.getCanonicalPath();
1583 boolean deleteDir = true;
1584 if (!docBasePath.startsWith(deployedPath)) {
1585 deleteDir = false;
1586 }
1587
1588
1589 if (debug >= 2) {
1590 log("Undeploying document base " + docBasePath);
1591 }
1592
1593 if (context.getPath().equals(this.context.getPath())) {
1594 writer.println(sm.getString("managerServlet.noSelf"));
1595 return;
1596 }
1597 boolean dir = docBaseDir.isDirectory();
1598 deployer.remove(path, true);
1599 if (deleteDir) {
1600 if (dir) {
1601 undeployDir(docBaseDir);
1602
1603 File docBaseWar = new File(docBasePath + ".war");
1604 docBaseWar.delete();
1605 } else {
1606
1607 docBaseDir.delete();
1608 }
1609 }
1610 File docBaseXml = new File(context.getConfigFile());
1611 docBaseXml.delete();
1612 writer.println(sm.getString("managerServlet.undeployed",
1613 displayPath));
1614
1615 } catch (Throwable t) {
1616 log("ManagerServlet.undeploy[" + displayPath + "]", t);
1617 writer.println(sm.getString("managerServlet.exception",
1618 t.toString()));
1619 }
1620
1621 }
1622
1623
1624
1625
1626
1627 /**
1628 * Given a context path, get the config file name.
1629 */
1630 protected String getConfigFile(String path) {
1631 String basename = null;
1632 if (path.equals("")) {
1633 basename = "ROOT";
1634 } else {
1635 basename = path.substring(1).replace('/', '#');
1636 }
1637 return (basename);
1638 }
1639
1640
1641 /**
1642 * Extract the context configuration file from the specified WAR,
1643 * if it is present. If it is not present, ensure that the corresponding
1644 * file does not exist.
1645 *
1646 * @param war File object representing the WAR
1647 * @param xml File object representing where to store the extracted
1648 * context configuration file (if it exists)
1649 *
1650 * @exception IOException if an i/o error occurs
1651 */
1652 protected void extractXml(File war, File xml) throws IOException {
1653
1654 xml.delete();
1655 JarFile jar = null;
1656 JarEntry entry = null;
1657 InputStream istream = null;
1658 BufferedOutputStream ostream = null;
1659 try {
1660 jar = new JarFile(war);
1661 entry = jar.getJarEntry("META-INF/context.xml");
1662 if (entry == null) {
1663 return;
1664 }
1665 istream = jar.getInputStream(entry);
1666 ostream =
1667 new BufferedOutputStream(new FileOutputStream(xml), 1024);
1668 byte buffer[] = new byte[1024];
1669 while (true) {
1670 int n = istream.read(buffer);
1671 if (n < 0) {
1672 break;
1673 }
1674 ostream.write(buffer, 0, n);
1675 }
1676 ostream.flush();
1677 ostream.close();
1678 ostream = null;
1679 istream.close();
1680 istream = null;
1681 entry = null;
1682 jar.close();
1683 jar = null;
1684 } catch (IOException e) {
1685 xml.delete();
1686 throw e;
1687 } finally {
1688 if (ostream != null) {
1689 try {
1690 ostream.close();
1691 } catch (Throwable t) {
1692 ;
1693 }
1694 ostream = null;
1695 }
1696 if (istream != null) {
1697 try {
1698 istream.close();
1699 } catch (Throwable t) {
1700 ;
1701 }
1702 istream = null;
1703 }
1704 entry = null;
1705 if (jar != null) {
1706 try {
1707 jar.close();
1708 } catch (Throwable t) {
1709 ;
1710 }
1711 jar = null;
1712 }
1713 }
1714
1715 }
1716
1717
1718 /**
1719 * Delete the specified directory, including all of its contents and
1720 * subdirectories recursively.
1721 *
1722 * @param dir File object representing the directory to be deleted
1723 */
1724 protected void undeployDir(File dir) {
1725
1726 String files[] = dir.list();
1727 if (files == null) {
1728 files = new String[0];
1729 }
1730 for (int i = 0; i < files.length; i++) {
1731 File file = new File(dir, files[i]);
1732 if (file.isDirectory()) {
1733 undeployDir(file);
1734 } else {
1735 file.delete();
1736 }
1737 }
1738 dir.delete();
1739
1740 }
1741
1742
1743 /**
1744 * Upload the WAR file included in this request, and store it at the
1745 * specified file location.
1746 *
1747 * @param request The servlet request we are processing
1748 * @param war The file into which we should store the uploaded WAR
1749 *
1750 * @exception IOException if an I/O error occurs during processing
1751 */
1752 protected void uploadWar(HttpServletRequest request, File war)
1753 throws IOException {
1754
1755 war.delete();
1756 ServletInputStream istream = null;
1757 BufferedOutputStream ostream = null;
1758 try {
1759 istream = request.getInputStream();
1760 ostream =
1761 new BufferedOutputStream(new FileOutputStream(war), 1024);
1762 byte buffer[] = new byte[1024];
1763 while (true) {
1764 int n = istream.read(buffer);
1765 if (n < 0) {
1766 break;
1767 }
1768 ostream.write(buffer, 0, n);
1769 }
1770 ostream.flush();
1771 ostream.close();
1772 ostream = null;
1773 istream.close();
1774 istream = null;
1775 } catch (IOException e) {
1776 war.delete();
1777 throw e;
1778 } finally {
1779 if (ostream != null) {
1780 try {
1781 ostream.close();
1782 } catch (Throwable t) {
1783 ;
1784 }
1785 ostream = null;
1786 }
1787 if (istream != null) {
1788 try {
1789 istream.close();
1790 } catch (Throwable t) {
1791 ;
1792 }
1793 istream = null;
1794 }
1795 }
1796
1797 }
1798
1799
1800 /**
1801 * Copy a file.
1802 */
1803 private boolean copy(File src, File dest) {
1804 FileInputStream is = null;
1805 FileOutputStream os = null;
1806 try {
1807 is = new FileInputStream(src);
1808 os = new FileOutputStream(dest);
1809 byte[] buf = new byte[4096];
1810 while (true) {
1811 int len = is.read(buf);
1812 if (len < 0)
1813 break;
1814 os.write(buf, 0, len);
1815 }
1816 is.close();
1817 os.close();
1818 } catch (IOException e) {
1819 return false;
1820 } finally {
1821 try {
1822 if (is != null) {
1823 is.close();
1824 }
1825 } catch (Exception e) {
1826
1827 }
1828 try {
1829 if (os != null) {
1830 os.close();
1831 }
1832 } catch (Exception e) {
1833
1834 }
1835 }
1836 return true;
1837 }
1838
1839 /**
1840 * Identify the appBase of the Host of Context
1841 * (if any)
1842 *
1843 * @param context context to obtain appBase
1844 *
1845 * @return File representing appBase directory
1846 */
1847 private File getDeployed(Context context) {
1848
1849 File deployed = null;
1850
1851 String appBase = ((Host) context.getParent()).getAppBase();
1852 deployed = new File(appBase);
1853 if (!deployed.isAbsolute()) {
1854 deployed = new File(System.getProperty("catalina.base"),
1855 appBase);
1856 }
1857
1858 return deployed;
1859
1860 }
1861
1862 }