001: ///** Copyright Statement ***************************************************
002: //The Salmon Open Framework for Internet Applications (SOFIA)
003: // Copyright (C) 1999 - 2002, Salmon LLC
004: //
005: // This program is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU General Public License version 2
007: // as published by the Free Software Foundation;
008: //
009: // This program is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: // GNU General Public License for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // along with this program; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: //
018: // For more information please visit http://www.salmonllc.com
019: //** End Copyright Statement ***************************************************
020: // ====================================================================
021: //
022: // The Apache Software License, Version 1.1
023: //
024: // Copyright (c) 1999 The Apache Software Foundation. All rights
025: // reserved.
026: //
027: // Redistribution and use in source and binary forms, with or without
028: // modification, are permitted provided that the following conditions
029: // are met:
030: //
031: // 1. Redistributions of source code must retain the above copyright
032: // notice, this list of conditions and the following disclaimer.
033: //
034: // 2. Redistributions in binary form must reproduce the above copyright
035: // notice, this list of conditions and the following disclaimer in
036: // the documentation and/or other materials provided with the
037: // distribution.
038: //
039: // 3. The end-user documentation included with the redistribution, if
040: // any, must include the following acknowlegement:
041: // "This product includes software developed by the
042: // Apache Software Foundation (http://www.apache.org/)."
043: // Alternately, this acknowlegement may appear in the software itself,
044: // if and wherever such third-party acknowlegements normally appear.
045: //
046: // 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
047: // Foundation" must not be used to endorse or promote products derived
048: // from this software without prior written permission. For written
049: // permission, please contact apache@apache.org.
050: //
051: // 5. Products derived from this software may not be called "Apache"
052: // nor may "Apache" appear in their names without prior written
053: // permission of the Apache Group.
054: //
055: // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
056: // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
057: // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
058: // DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
059: // ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
060: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
061: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
062: // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
063: // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
064: // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
065: // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
066: // SUCH DAMAGE.
067: // ====================================================================
068: //
069: // This software consists of voluntary contributions made by many
070: // individuals on behalf of the Apache Software Foundation. For more
071: // information on the Apache Software Foundation, please see
072: // <http://www.apache.org/>.
073:
074: package com.salmonllc.ideTools;
075:
076: import java.io.File;
077: import java.io.FileInputStream;
078: import java.io.IOException;
079: import java.io.OutputStream;
080: import java.net.Socket;
081: import java.security.Security;
082:
083: import org.apache.catalina.Lifecycle;
084: import org.apache.catalina.LifecycleException;
085: import org.apache.catalina.Server;
086: import org.apache.catalina.startup.ContextRuleSet;
087: import org.apache.catalina.startup.EngineRuleSet;
088: import org.apache.catalina.startup.HostRuleSet;
089: import org.apache.catalina.startup.NamingRuleSet;
090: import org.apache.commons.digester.Digester;
091: import org.apache.tomcat.util.log.SystemLogHandler;
092: import org.xml.sax.InputSource;
093:
094: import com.salmonllc.util.MessageLog;
095:
096: /**
097: * Startup/Shutdown shell program for Catalina. The following command line
098: * options are recognized:
099: * <ul>
100: * <li><b>-config {pathname}</b> - Set the pathname of the configuration file
101: * to be processed. If a relative path is specified, it will be
102: * interpreted as relative to the directory pathname specified by the
103: * "catalina.base" system property. [conf/server.xml]
104: * <li><b>-help</b> - Display usage information.
105: * <li><b>-stop</b> - Stop the currently running instance of Catalina.
106: * </u>
107: *
108: * @author Craig R. McClanahan
109: * @version $Revision: 4 $ $Date: 7/29/04 11:08a $
110: */
111:
112: public class Tomcat41Engine {
113:
114: // ----------------------------------------------------- Instance Variables
115:
116: //Salmon Added
117: private Process _browserProcess = null;
118: private Tomcat41Bootstrap _bootstrap;
119: private Tomcat41ShutdownProperties _shutdown;
120: //End Salmon Added
121:
122: /**
123: * Pathname to the server configuration file.
124: */
125: protected String configFile = "conf/server.xml";
126:
127: /**
128: * Set the debugging detail level on our Digester.
129: */
130: protected boolean debug = false;
131:
132: /**
133: * The shared extensions class loader for this server.
134: */
135: protected ClassLoader parentClassLoader = ClassLoader
136: .getSystemClassLoader();
137:
138: /**
139: * The server component we are starting or stopping
140: */
141: protected Server server = null;
142:
143: /**
144: * Are we starting a new server?
145: */
146: protected boolean starting = false;
147:
148: /**
149: * Are we stopping an existing server?
150: */
151: protected boolean stopping = false;
152:
153: /**
154: * Are we using naming ?
155: */
156: protected boolean useNaming = true;
157:
158: // ----------------------------------------------------------- Main Program
159:
160: /**
161: * The application main program.
162: *
163: * @param args Command line arguments
164: */
165: public static void main(String args[]) {
166:
167: (new Tomcat41Engine()).process(args);
168: }
169:
170: /**
171: * The instance main program.
172: *
173: * @param args Command line arguments
174: */
175: public void process(String args[]) {
176: setCatalinaHome();
177: setCatalinaBase();
178: try {
179: if (arguments(args))
180: execute();
181: } catch (Exception e) {
182: e.printStackTrace(System.out);
183: }
184: }
185:
186: // --------------------------------------------------------- Public Methods
187:
188: /**
189: * Set the shared extensions class loader.
190: *
191: * @param parentClassLoader The shared extensions class loader.
192: */
193: public void setParentClassLoader(ClassLoader parentClassLoader) {
194:
195: this .parentClassLoader = parentClassLoader;
196:
197: }
198:
199: /**
200: * Set the server instance we are configuring.
201: *
202: * @param server The new server
203: */
204: public void setServer(Server server) {
205:
206: this .server = server;
207:
208: }
209:
210: /**
211: * Sets the shutdown properties for this server
212: */
213: public void setShutdownProperties(Tomcat41ShutdownProperties props) {
214: _shutdown = props;
215: }
216:
217: // ------------------------------------------------------ Protected Methods
218:
219: /**
220: * Process the specified command line arguments, and return
221: * <code>true</code> if we should continue processing; otherwise
222: * return <code>false</code>.
223: *
224: * @param args Command line arguments to process
225: */
226: protected boolean arguments(String args[]) {
227:
228: boolean isConfig = false;
229:
230: if (args.length < 1) {
231: usage();
232: return (false);
233: }
234:
235: for (int i = 0; i < args.length; i++) {
236: if (isConfig) {
237: configFile = args[i];
238: isConfig = false;
239: } else if (args[i].equals("-config")) {
240: isConfig = true;
241: } else if (args[i].equals("-debug")) {
242: debug = true;
243: } else if (args[i].equals("-nonaming")) {
244: useNaming = false;
245: } else if (args[i].equals("-help")) {
246: usage();
247: return (false);
248: } else if (args[i].equals("start")) {
249: starting = true;
250: } else if (args[i].equals("stop")) {
251: stopping = true;
252: } else {
253: usage();
254: return (false);
255: }
256: }
257:
258: return (true);
259:
260: }
261:
262: /**
263: * Return a File object representing our configuration file.
264: */
265: protected File configFile() {
266:
267: File file = new File(configFile);
268: if (!file.isAbsolute())
269: file = new File(System.getProperty("catalina.base"),
270: configFile);
271: return (file);
272:
273: }
274:
275: /**
276: * Create and configure the Digester we will be using for startup.
277: */
278: protected Digester createStartDigester() {
279:
280: // Initialize the digester
281: Digester digester = new Digester();
282: if (debug)
283: digester.setDebug(999);
284: digester.setValidating(false);
285:
286: // Configure the actions we will be using
287: digester.addObjectCreate("Server",
288: "org.apache.catalina.core.StandardServer", "className");
289: digester.addSetProperties("Server");
290: digester.addSetNext("Server", "setServer",
291: "org.apache.catalina.Server");
292:
293: digester.addObjectCreate("Server/GlobalNamingResources",
294: "org.apache.catalina.deploy.NamingResources");
295: digester.addSetProperties("Server/GlobalNamingResources");
296: digester.addSetNext("Server/GlobalNamingResources",
297: "setGlobalNamingResources",
298: "org.apache.catalina.deploy.NamingResources");
299:
300: digester.addObjectCreate("Server/Listener", null, // MUST be specified in the element
301: "className");
302: digester.addSetProperties("Server/Listener");
303: digester.addSetNext("Server/Listener", "addLifecycleListener",
304: "org.apache.catalina.LifecycleListener");
305:
306: digester
307: .addObjectCreate("Server/Service",
308: "org.apache.catalina.core.StandardService",
309: "className");
310: digester.addSetProperties("Server/Service");
311: digester.addSetNext("Server/Service", "addService",
312: "org.apache.catalina.Service");
313:
314: digester.addObjectCreate("Server/Service/Listener", null, // MUST be specified in the element
315: "className");
316: digester.addSetProperties("Server/Service/Listener");
317: digester.addSetNext("Server/Service/Listener",
318: "addLifecycleListener",
319: "org.apache.catalina.LifecycleListener");
320:
321: digester.addObjectCreate("Server/Service/Connector",
322: "org.apache.catalina.connector.http.HttpConnector",
323: "className");
324: digester.addSetProperties("Server/Service/Connector");
325: digester.addSetNext("Server/Service/Connector", "addConnector",
326: "org.apache.catalina.Connector");
327:
328: digester.addObjectCreate("Server/Service/Connector/Factory",
329: "org.apache.catalina.net.DefaultServerSocketFactory",
330: "className");
331: digester.addSetProperties("Server/Service/Connector/Factory");
332: digester.addSetNext("Server/Service/Connector/Factory",
333: "setFactory",
334: "org.apache.catalina.net.ServerSocketFactory");
335:
336: digester.addObjectCreate("Server/Service/Connector/Listener",
337: null, // MUST be specified in the element
338: "className");
339: digester.addSetProperties("Server/Service/Connector/Listener");
340: digester.addSetNext("Server/Service/Connector/Listener",
341: "addLifecycleListener",
342: "org.apache.catalina.LifecycleListener");
343:
344: // Add RuleSets for nested elements
345: digester.addRuleSet(new NamingRuleSet(
346: "Server/GlobalNamingResources/"));
347: digester.addRuleSet(new EngineRuleSet("Server/Service/"));
348: digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
349: digester.addRuleSet(new ContextRuleSet(
350: "Server/Service/Engine/Default"));
351: digester.addRuleSet(new NamingRuleSet(
352: "Server/Service/Engine/DefaultContext/"));
353: digester.addRuleSet(new ContextRuleSet(
354: "Server/Service/Engine/Host/Default"));
355: digester.addRuleSet(new NamingRuleSet(
356: "Server/Service/Engine/Host/DefaultContext/"));
357: digester.addRuleSet(new ContextRuleSet(
358: "Server/Service/Engine/Host/"));
359: digester.addRuleSet(new NamingRuleSet(
360: "Server/Service/Engine/Host/Context/"));
361:
362: //digester.addRule("Server/Service/Engine",
363: // new SetParentClassLoaderRule(digester,
364: // parentClassLoader));
365:
366: return (digester);
367:
368: }
369:
370: /**
371: * Create and configure the Digester we will be using for shutdown.
372: */
373: protected Digester createStopDigester() {
374:
375: // Initialize the digester
376: Digester digester = new Digester();
377: if (debug)
378: digester.setDebug(999);
379:
380: // Configure the rules we need for shutting down
381: digester.addObjectCreate("Server",
382: "com.salmonllc.ideTools.Tomcat41ShutdownProperties",
383: "className");
384: digester.addSetProperties("Server");
385: digester.addSetNext("Server", "setShutdownProperties",
386: "com.salmonllc.ideTools.Tomcat41ShutdownProperties");
387:
388: return (digester);
389:
390: }
391:
392: /**
393: * Execute the processing that has been configured from the command line.
394: */
395: protected void execute() throws Exception {
396:
397: if (starting)
398: start();
399: else if (stopping)
400: stop();
401:
402: }
403:
404: /**
405: * Set the <code>catalina.base</code> System property to the current
406: * working directory if it has not been set.
407: */
408: protected void setCatalinaBase() {
409:
410: if (System.getProperty("catalina.base") != null)
411: return;
412: System.setProperty("catalina.base", System
413: .getProperty("catalina.home"));
414:
415: }
416:
417: /**
418: * Set the <code>catalina.home</code> System property to the current
419: * working directory if it has not been set.
420: */
421: protected void setCatalinaHome() {
422:
423: if (System.getProperty("catalina.home") != null)
424: return;
425: System.setProperty("catalina.home", System
426: .getProperty("user.dir"));
427:
428: }
429:
430: /**
431: * Start a new server instance.
432: */
433: protected void start() {
434:
435: // Create and execute our Digester
436: Digester digester = createStartDigester();
437: File file = configFile();
438: try {
439: InputSource is = new InputSource("file://"
440: + file.getAbsolutePath());
441: FileInputStream fis = new FileInputStream(file);
442: is.setByteStream(fis);
443: digester.push(this );
444: digester.parse(is);
445: fis.close();
446: } catch (Exception e) {
447: System.out.println("Catalina.start: " + e);
448: e.printStackTrace(System.out);
449: System.exit(1);
450: }
451:
452: // Setting additional variables
453: if (!useNaming) {
454: System.setProperty("catalina.useNaming", "false");
455: } else {
456: System.setProperty("catalina.useNaming", "true");
457: String value = "org.apache.naming";
458: String oldValue = System
459: .getProperty(javax.naming.Context.URL_PKG_PREFIXES);
460: if (oldValue != null) {
461: value = value + ":" + oldValue;
462: }
463: System.setProperty(javax.naming.Context.URL_PKG_PREFIXES,
464: value);
465: value = System
466: .getProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY);
467: if (value == null) {
468: System.setProperty(
469: javax.naming.Context.INITIAL_CONTEXT_FACTORY,
470: "org.apache.naming.java.javaURLContextFactory");
471: }
472: }
473:
474: // If a SecurityManager is being used, set properties for
475: // checkPackageAccess() and checkPackageDefinition
476: if (System.getSecurityManager() != null) {
477: String access = Security.getProperty("package.access");
478: if (access != null && access.length() > 0)
479: access += ",";
480: else
481: access = "sun.,";
482: Security.setProperty("package.access", access
483: + "org.apache.catalina.,org.apache.jasper.");
484: String definition = Security
485: .getProperty("package.definition");
486: if (definition != null && definition.length() > 0)
487: definition += ",";
488: else
489: definition = "sun.,";
490: Security
491: .setProperty("package.definition",
492: // FIX ME package "javax." was removed to prevent HotSpot
493: // fatal internal errors
494: definition
495: + "java.,org.apache.catalina.,org.apache.jasper.");
496: }
497:
498: // Replace System.out and System.err with a custom PrintStream
499: SystemLogHandler log = new SystemLogHandler(System.out);
500: System.setOut(log);
501: System.setErr(log);
502:
503: //Thread shutdownHook = new CatalinaShutdownHook();
504:
505: // Start the new server
506: if (server instanceof Lifecycle) {
507: try {
508: server.initialize();
509: ((Lifecycle) server).start();
510: /* try {
511: // Register shutdown hook
512: Runtime.getRuntime().addShutdownHook(shutdownHook);
513: } catch (Throwable t) {
514: // This will fail on JDK 1.2. Ignoring, as Tomcat can run
515: // fine without the shutdown hook.
516: }*/
517:
518: if (_bootstrap != null) {
519: if (_bootstrap.getBrowserExe() != null)
520: runBrowser(_bootstrap.getBrowserExe(),
521: _bootstrap.getBrowserURL());
522: _bootstrap.notifyComplete();
523: }
524:
525: // Wait for the server to be told to shut down*/
526: server.await();
527:
528: //Stop the browser process if there is one
529: if (_browserProcess != null) {
530: _browserProcess.destroy();
531: }
532: //It takes too long to stop the server the normal way so we will just terminate the process
533: System.out.println("Apache Tomcat stopped");
534: System.exit(0);
535:
536: } catch (LifecycleException e) {
537: System.out.println("Catalina.start: " + e);
538: e.printStackTrace(System.out);
539: if (e.getThrowable() != null) {
540: System.out.println("----- Root Cause -----");
541: e.getThrowable().printStackTrace(System.out);
542: }
543: }
544: }
545:
546: // Shut down the server
547: /*if (server instanceof Lifecycle) {
548: try {
549: try {
550: // Remove the ShutdownHook first so that server.stop()
551: // doesn't get invoked twice
552: Runtime.getRuntime().removeShutdownHook(shutdownHook);
553: } catch (Throwable t) {
554: // This will fail on JDK 1.2. Ignoring, as Tomcat can run
555: // fine without the shutdown hook.
556: }
557: ((Lifecycle) server).stop();
558: } catch (LifecycleException e) {
559: System.out.println("Catalina.stop: " + e);
560: e.printStackTrace(System.out);
561: if (e.getThrowable() != null) {
562: System.out.println("----- Root Cause -----");
563: e.getThrowable().printStackTrace(System.out);
564: }
565: }
566: } */
567:
568: }
569:
570: /**
571: * Stop an existing server instance.
572: */
573: protected void stop() {
574:
575: // Create and execute our Digester
576: Digester digester = createStopDigester();
577: File file = configFile();
578: try {
579: InputSource is = new InputSource("file://"
580: + file.getAbsolutePath());
581: FileInputStream fis = new FileInputStream(file);
582: is.setByteStream(fis);
583: digester.push(this );
584: digester.parse(is);
585: fis.close();
586: } catch (Exception e) {
587: System.out.println("Catalina.stop: " + e);
588: e.printStackTrace(System.out);
589: System.exit(1);
590: }
591:
592: // Stop the existing server
593: try {
594: String host = "127.0.0.1";
595: int port = 8005;
596: String shutdown = "SHUTDOWN";
597:
598: if (_shutdown != null) {
599: port = _shutdown.getPort();
600: shutdown = _shutdown.getShutdown();
601: }
602:
603: Socket socket = new Socket(host, port);
604: OutputStream stream = socket.getOutputStream();
605:
606: for (int i = 0; i < shutdown.length(); i++)
607: stream.write(shutdown.charAt(i));
608: stream.flush();
609: stream.close();
610: socket.close();
611: Thread.sleep(500);
612: } catch (Exception e) {
613: //System.out.println("Catalina.stop: " + e);
614: //e.printStackTrace(System.out);
615: //System.exit(1);
616: }
617:
618: if (_bootstrap != null)
619: _bootstrap.notifyComplete();
620:
621: }
622:
623: /**
624: * Print usage information for this application.
625: */
626: protected void usage() {
627:
628: System.out
629: .println("usage: java org.apache.catalina.startup.Catalina"
630: + " [ -config {pathname} ] [ -debug ]"
631: + " [ -nonaming ] { start | stop }");
632:
633: }
634:
635: public void finalize() {
636: if (_browserProcess != null)
637: _browserProcess.destroy();
638: }
639:
640: public void process(String args[], Tomcat41Bootstrap bootstrap) {
641: _bootstrap = bootstrap;
642: process(args);
643: }
644:
645: private void runBrowser(String command, String parms) {
646: Runtime r = Runtime.getRuntime();
647: String env[] = new String[0];
648:
649: try {
650: _browserProcess = r.exec('"' + command + '"'
651: + (parms == null ? "" : (" " + parms)));
652: IDETool.slurpProcessOutput(_browserProcess);
653: } catch (IOException e) {
654: MessageLog.writeErrorMessage("runBrowser", e, this );
655: }
656: }
657:
658: // --------------------------------------- CatalinaShutdownHook Inner Class
659:
660: /**
661: * Shutdown hook which will perform a clean shutdown of Catalina if needed.
662: */
663: protected class CatalinaShutdownHook extends Thread {
664:
665: public void run() {
666:
667: if (server != null) {
668: try {
669: ((Lifecycle) server).stop();
670: } catch (LifecycleException e) {
671: System.out.println("Catalina.stop: " + e);
672: e.printStackTrace(System.out);
673: if (e.getThrowable() != null) {
674: System.out.println("----- Root Cause -----");
675: e.getThrowable().printStackTrace(System.out);
676: }
677: }
678: }
679:
680: }
681:
682: }
683:
684: }
685:
686: // ------------------------------------------------------------ Private Classes
|