KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > startup > Catalina


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

17
18
19 package org.apache.catalina.startup;
20
21
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.net.Socket JavaDoc;
28 import org.apache.catalina.Container;
29 import org.apache.catalina.Lifecycle;
30 import org.apache.catalina.LifecycleException;
31 import org.apache.catalina.Server;
32 import org.apache.catalina.core.StandardServer;
33 import org.apache.tomcat.util.digester.Digester;
34 import org.apache.tomcat.util.digester.Rule;
35 import org.xml.sax.Attributes JavaDoc;
36 import org.xml.sax.InputSource JavaDoc;
37
38
39 /**
40  * Startup/Shutdown shell program for Catalina. The following command line
41  * options are recognized:
42  * <ul>
43  * <li><b>-config {pathname}</b> - Set the pathname of the configuration file
44  * to be processed. If a relative path is specified, it will be
45  * interpreted as relative to the directory pathname specified by the
46  * "catalina.base" system property. [conf/server.xml]
47  * <li><b>-help</b> - Display usage information.
48  * <li><b>-stop</b> - Stop the currently running instance of Catalina.
49  * </u>
50  *
51  * Should do the same thing as Embedded, but using a server.xml file.
52  *
53  * @author Craig R. McClanahan
54  * @author Remy Maucherat
55  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
56  */

57
58 public class Catalina extends Embedded {
59
60
61     // ----------------------------------------------------- Instance Variables
62

63
64     /**
65      * Pathname to the server configuration file.
66      */

67     protected String JavaDoc configFile = "conf/server.xml";
68
69     // XXX Should be moved to embedded
70
/**
71      * The shared extensions class loader for this server.
72      */

73     protected ClassLoader JavaDoc parentClassLoader =
74         Catalina.class.getClassLoader();
75
76
77     /**
78      * The server component we are starting or stopping
79      */

80     protected Server server = null;
81
82
83     /**
84      * Are we starting a new server?
85      */

86     protected boolean starting = false;
87
88
89     /**
90      * Are we stopping an existing server?
91      */

92     protected boolean stopping = false;
93
94
95     /**
96      * Use shutdown hook flag.
97      */

98     protected boolean useShutdownHook = true;
99
100
101     /**
102      * Shutdown hook.
103      */

104     protected Thread JavaDoc shutdownHook = null;
105
106
107     // ------------------------------------------------------------- Properties
108

109
110     public void setConfig(String JavaDoc file) {
111         configFile = file;
112     }
113
114
115     public void setConfigFile(String JavaDoc file) {
116         configFile = file;
117     }
118
119
120     public String JavaDoc getConfigFile() {
121         return configFile;
122     }
123
124
125     public void setUseShutdownHook(boolean useShutdownHook) {
126         this.useShutdownHook = useShutdownHook;
127     }
128
129
130     public boolean getUseShutdownHook() {
131         return useShutdownHook;
132     }
133
134
135     /**
136      * Set the shared extensions class loader.
137      *
138      * @param parentClassLoader The shared extensions class loader.
139      */

140     public void setParentClassLoader(ClassLoader JavaDoc parentClassLoader) {
141
142         this.parentClassLoader = parentClassLoader;
143
144     }
145
146
147     /**
148      * Set the server instance we are configuring.
149      *
150      * @param server The new server
151      */

152     public void setServer(Server server) {
153
154         this.server = server;
155
156     }
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 JavaDoc args[]) {
166         (new Catalina()).process(args);
167     }
168
169
170     /**
171      * The instance main program.
172      *
173      * @param args Command line arguments
174      */

175     public void process(String JavaDoc args[]) {
176
177         setAwait(true);
178         setCatalinaHome();
179         setCatalinaBase();
180         try {
181             if (arguments(args)) {
182                 if (starting) {
183                     load(args);
184                     start();
185                 } else if (stopping) {
186                     stopServer();
187                 }
188             }
189         } catch (Exception JavaDoc e) {
190             e.printStackTrace(System.out);
191         }
192     }
193
194
195     // ------------------------------------------------------ Protected Methods
196

197
198     /**
199      * Process the specified command line arguments, and return
200      * <code>true</code> if we should continue processing; otherwise
201      * return <code>false</code>.
202      *
203      * @param args Command line arguments to process
204      */

205     protected boolean arguments(String JavaDoc args[]) {
206
207         boolean isConfig = false;
208
209         if (args.length < 1) {
210             usage();
211             return (false);
212         }
213
214         for (int i = 0; i < args.length; i++) {
215             if (isConfig) {
216                 configFile = args[i];
217                 isConfig = false;
218             } else if (args[i].equals("-config")) {
219                 isConfig = true;
220             } else if (args[i].equals("-nonaming")) {
221                 setUseNaming( false );
222             } else if (args[i].equals("-help")) {
223                 usage();
224                 return (false);
225             } else if (args[i].equals("start")) {
226                 starting = true;
227                 stopping = false;
228             } else if (args[i].equals("stop")) {
229                 starting = false;
230                 stopping = true;
231             } else {
232                 usage();
233                 return (false);
234             }
235         }
236
237         return (true);
238
239     }
240
241
242     /**
243      * Return a File object representing our configuration file.
244      */

245     protected File JavaDoc configFile() {
246
247         File JavaDoc file = new File JavaDoc(configFile);
248         if (!file.isAbsolute())
249             file = new File JavaDoc(System.getProperty("catalina.base"), configFile);
250         return (file);
251
252     }
253
254
255     /**
256      * Create and configure the Digester we will be using for startup.
257      */

258     protected Digester createStartDigester() {
259         long t1=System.currentTimeMillis();
260         // Initialize the digester
261
Digester digester = new Digester();
262         digester.setValidating(false);
263         digester.setClassLoader(StandardServer.class.getClassLoader());
264
265         // Configure the actions we will be using
266
digester.addObjectCreate("Server",
267                                  "org.apache.catalina.core.StandardServer",
268                                  "className");
269         digester.addSetProperties("Server");
270         digester.addSetNext("Server",
271                             "setServer",
272                             "org.apache.catalina.Server");
273
274         digester.addObjectCreate("Server/GlobalNamingResources",
275                                  "org.apache.catalina.deploy.NamingResources");
276         digester.addSetProperties("Server/GlobalNamingResources");
277         digester.addSetNext("Server/GlobalNamingResources",
278                             "setGlobalNamingResources",
279                             "org.apache.catalina.deploy.NamingResources");
280
281         digester.addObjectCreate("Server/Listener",
282                                  null, // MUST be specified in the element
283
"className");
284         digester.addSetProperties("Server/Listener");
285         digester.addSetNext("Server/Listener",
286                             "addLifecycleListener",
287                             "org.apache.catalina.LifecycleListener");
288
289         digester.addObjectCreate("Server/Service",
290                                  "org.apache.catalina.core.StandardService",
291                                  "className");
292         digester.addSetProperties("Server/Service");
293         digester.addSetNext("Server/Service",
294                             "addService",
295                             "org.apache.catalina.Service");
296
297         digester.addObjectCreate("Server/Service/Listener",
298                                  null, // MUST be specified in the element
299
"className");
300         digester.addSetProperties("Server/Service/Listener");
301         digester.addSetNext("Server/Service/Listener",
302                             "addLifecycleListener",
303                             "org.apache.catalina.LifecycleListener");
304
305         digester.addRule("Server/Service/Connector",
306                          new ConnectorCreateRule());
307         digester.addRule("Server/Service/Connector",
308                          new SetAllPropertiesRule());
309         digester.addSetNext("Server/Service/Connector",
310                             "addConnector",
311                             "org.apache.catalina.connector.Connector");
312
313         digester.addObjectCreate("Server/Service/Connector/Listener",
314                                  null, // MUST be specified in the element
315
"className");
316         digester.addSetProperties("Server/Service/Connector/Listener");
317         digester.addSetNext("Server/Service/Connector/Listener",
318                             "addLifecycleListener",
319                             "org.apache.catalina.LifecycleListener");
320
321         // Add RuleSets for nested elements
322
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
323         digester.addRuleSet(new EngineRuleSet("Server/Service/"));
324         digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
325         digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
326         digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
327         digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
328
329         // When the 'engine' is found, set the parentClassLoader.
330
digester.addRule("Server/Service/Engine",
331                          new SetParentClassLoaderRule(parentClassLoader));
332         digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/"));
333
334         long t2=System.currentTimeMillis();
335         if (log.isDebugEnabled())
336             log.debug("Digester for server.xml created " + ( t2-t1 ));
337         return (digester);
338
339     }
340
341
342     /**
343      * Create and configure the Digester we will be using for shutdown.
344      */

345     protected Digester createStopDigester() {
346
347         // Initialize the digester
348
Digester digester = new Digester();
349
350         // Configure the rules we need for shutting down
351
digester.addObjectCreate("Server",
352                                  "org.apache.catalina.core.StandardServer",
353                                  "className");
354         digester.addSetProperties("Server");
355         digester.addSetNext("Server",
356                             "setServer",
357                             "org.apache.catalina.Server");
358
359         return (digester);
360
361     }
362
363
364     public void stopServer() {
365         stopServer(null);
366     }
367
368     public void stopServer(String JavaDoc[] arguments) {
369
370         if (arguments != null) {
371             arguments(arguments);
372         }
373
374         if( server == null ) {
375             // Create and execute our Digester
376
Digester digester = createStopDigester();
377             digester.setClassLoader(Thread.currentThread().getContextClassLoader());
378             File JavaDoc file = configFile();
379             try {
380                 InputSource JavaDoc is =
381                     new InputSource JavaDoc("file://" + file.getAbsolutePath());
382                 FileInputStream JavaDoc fis = new FileInputStream JavaDoc(file);
383                 is.setByteStream(fis);
384                 digester.push(this);
385                 digester.parse(is);
386                 fis.close();
387             } catch (Exception JavaDoc e) {
388                 log.error("Catalina.stop: ", e);
389                 System.exit(1);
390             }
391         }
392
393         // Stop the existing server
394
try {
395             Socket JavaDoc socket = new Socket JavaDoc("127.0.0.1", server.getPort());
396             OutputStream JavaDoc stream = socket.getOutputStream();
397             String JavaDoc shutdown = server.getShutdown();
398             for (int i = 0; i < shutdown.length(); i++)
399                 stream.write(shutdown.charAt(i));
400             stream.flush();
401             stream.close();
402             socket.close();
403         } catch (IOException JavaDoc e) {
404             log.error("Catalina.stop: ", e);
405             System.exit(1);
406         }
407
408     }
409
410
411     /**
412      * Set the <code>catalina.base</code> System property to the current
413      * working directory if it has not been set.
414      * @deprecated Use initDirs()
415      */

416     public void setCatalinaBase() {
417         initDirs();
418     }
419
420     /**
421      * Set the <code>catalina.home</code> System property to the current
422      * working directory if it has not been set.
423      * @deprecated Use initDirs()
424      */

425     public void setCatalinaHome() {
426         initDirs();
427     }
428
429     /**
430      * Start a new server instance.
431      */

432     public void load() {
433
434         initDirs();
435
436         // Before digester - it may be needed
437

438         initNaming();
439
440         // Create and execute our Digester
441
Digester digester = createStartDigester();
442         long t1 = System.currentTimeMillis();
443
444         Exception JavaDoc ex = null;
445         InputSource JavaDoc inputSource = null;
446         InputStream JavaDoc inputStream = null;
447         File JavaDoc file = null;
448         try {
449             file = configFile();
450             inputStream = new FileInputStream JavaDoc(file);
451             inputSource = new InputSource JavaDoc("file://" + file.getAbsolutePath());
452         } catch (Exception JavaDoc e) {
453             ;
454         }
455         if (inputStream == null) {
456             try {
457                 inputStream = getClass().getClassLoader()
458                     .getResourceAsStream(getConfigFile());
459                 inputSource = new InputSource JavaDoc
460                     (getClass().getClassLoader()
461                      .getResource(getConfigFile()).toString());
462             } catch (Exception JavaDoc e) {
463                 ;
464             }
465         }
466
467         // This should be included in catalina.jar
468
// Alternative: don't bother with xml, just create it manually.
469
if( inputStream==null ) {
470             try {
471                 inputStream = getClass().getClassLoader()
472                 .getResourceAsStream("server-embed.xml");
473                 inputSource = new InputSource JavaDoc
474                 (getClass().getClassLoader()
475                         .getResource("server-embed.xml").toString());
476             } catch (Exception JavaDoc e) {
477                 ;
478             }
479         }
480         
481
482         if ((inputStream == null) && (file != null)) {
483             log.warn("Can't load server.xml from " + file.getAbsolutePath());
484             return;
485         }
486
487         try {
488             inputSource.setByteStream(inputStream);
489             digester.push(this);
490             digester.parse(inputSource);
491             inputStream.close();
492         } catch (Exception JavaDoc e) {
493             log.warn("Catalina.start using "
494                                + getConfigFile() + ": " , e);
495             return;
496         }
497
498         // Stream redirection
499
initStreams();
500
501         // Start the new server
502
if (server instanceof Lifecycle) {
503             try {
504                 server.initialize();
505             } catch (LifecycleException e) {
506                 log.error("Catalina.start", e);
507             }
508         }
509
510         long t2 = System.currentTimeMillis();
511         if(log.isInfoEnabled())
512             log.info("Initialization processed in " + (t2 - t1) + " ms");
513
514     }
515
516
517     /*
518      * Load using arguments
519      */

520     public void load(String JavaDoc args[]) {
521
522         try {
523             if (arguments(args))
524                 load();
525         } catch (Exception JavaDoc e) {
526             e.printStackTrace(System.out);
527         }
528     }
529
530     public void create() {
531
532     }
533
534     public void destroy() {
535
536     }
537
538     /**
539      * Start a new server instance.
540      */

541     public void start() {
542
543         if (server == null) {
544             load();
545         }
546
547         long t1 = System.currentTimeMillis();
548
549         // Start the new server
550
if (server instanceof Lifecycle) {
551             try {
552                 ((Lifecycle) server).start();
553             } catch (LifecycleException e) {
554                 log.error("Catalina.start: ", e);
555             }
556         }
557
558         long t2 = System.currentTimeMillis();
559         if(log.isInfoEnabled())
560             log.info("Server startup in " + (t2 - t1) + " ms");
561
562         try {
563             // Register shutdown hook
564
if (useShutdownHook) {
565                 if (shutdownHook == null) {
566                     shutdownHook = new CatalinaShutdownHook();
567                 }
568                 Runtime.getRuntime().addShutdownHook(shutdownHook);
569             }
570         } catch (Throwable JavaDoc t) {
571             // This will fail on JDK 1.2. Ignoring, as Tomcat can run
572
// fine without the shutdown hook.
573
}
574
575         if (await) {
576             await();
577             stop();
578         }
579
580     }
581
582
583     /**
584      * Stop an existing server instance.
585      */

586     public void stop() {
587
588         try {
589             // Remove the ShutdownHook first so that server.stop()
590
// doesn't get invoked twice
591
if (useShutdownHook) {
592                 Runtime.getRuntime().removeShutdownHook(shutdownHook);
593             }
594         } catch (Throwable JavaDoc t) {
595             // This will fail on JDK 1.2. Ignoring, as Tomcat can run
596
// fine without the shutdown hook.
597
}
598
599         // Shut down the server
600
if (server instanceof Lifecycle) {
601             try {
602                 ((Lifecycle) server).stop();
603             } catch (LifecycleException e) {
604                 log.error("Catalina.stop", e);
605             }
606         }
607
608     }
609
610
611     /**
612      * Await and shutdown.
613      */

614     public void await() {
615
616         server.await();
617
618     }
619
620
621     /**
622      * Print usage information for this application.
623      */

624     protected void usage() {
625
626         System.out.println
627             ("usage: java org.apache.catalina.startup.Catalina"
628              + " [ -config {pathname} ]"
629              + " [ -nonaming ] { start | stop }");
630
631     }
632
633
634     // --------------------------------------- CatalinaShutdownHook Inner Class
635

636     // XXX Should be moved to embedded !
637
/**
638      * Shutdown hook which will perform a clean shutdown of Catalina if needed.
639      */

640     protected class CatalinaShutdownHook extends Thread JavaDoc {
641
642         public void run() {
643
644             if (server != null) {
645                 Catalina.this.stop();
646             }
647             
648         }
649
650     }
651     
652     
653     private static org.apache.commons.logging.Log log=
654         org.apache.commons.logging.LogFactory.getLog( Catalina.class );
655
656 }
657
658
659 // ------------------------------------------------------------ Private Classes
660

661
662 /**
663  * Rule that sets the parent class loader for the top object on the stack,
664  * which must be a <code>Container</code>.
665  */

666
667 final class SetParentClassLoaderRule extends Rule {
668
669     public SetParentClassLoaderRule(ClassLoader JavaDoc parentClassLoader) {
670
671         this.parentClassLoader = parentClassLoader;
672
673     }
674
675     ClassLoader JavaDoc parentClassLoader = null;
676
677     public void begin(String JavaDoc namespace, String JavaDoc name, Attributes JavaDoc attributes)
678         throws Exception JavaDoc {
679
680         if (digester.getLogger().isDebugEnabled())
681             digester.getLogger().debug("Setting parent class loader");
682
683         Container top = (Container) digester.peek();
684         top.setParentClassLoader(parentClassLoader);
685
686     }
687
688
689 }
690
Popular Tags