Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » startup » [javadoc | source]
    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;
   23   import java.io.FileInputStream;
   24   import java.io.IOException;
   25   import java.io.InputStream;
   26   import java.io.OutputStream;
   27   import java.net.InetAddress;
   28   import java.net.Socket;
   29   import java.util.ArrayList;
   30   import java.util.HashMap;
   31   import java.util.List;
   32   import java.util.logging.LogManager;
   33   
   34   import org.apache.catalina.Container;
   35   import org.apache.catalina.Lifecycle;
   36   import org.apache.catalina.LifecycleException;
   37   import org.apache.catalina.core.StandardServer;
   38   import org.apache.juli.ClassLoaderLogManager;
   39   import org.apache.tomcat.util.digester.Digester;
   40   import org.apache.tomcat.util.digester.Rule;
   41   import org.xml.sax.Attributes;
   42   import org.xml.sax.InputSource;
   43   
   44   
   45   /**
   46    * Startup/Shutdown shell program for Catalina.  The following command line
   47    * options are recognized:
   48    * <ul>
   49    * <li><b>-config {pathname}</b> - Set the pathname of the configuration file
   50    *     to be processed.  If a relative path is specified, it will be
   51    *     interpreted as relative to the directory pathname specified by the
   52    *     "catalina.base" system property.   [conf/server.xml]
   53    * <li><b>-help</b>      - Display usage information.
   54    * <li><b>-nonaming</b>  - Disable naming support.
   55    * <li><b>start</b>      - Start an instance of Catalina.
   56    * <li><b>stop</b>       - Stop the currently running instance of Catalina.
   57    * </u>
   58    *
   59    * Should do the same thing as Embedded, but using a server.xml file.
   60    *
   61    * @author Craig R. McClanahan
   62    * @author Remy Maucherat
   63    * @version $Revision: 919742 $ $Date: 2010-03-06 12:15:07 +0100 (Sat, 06 Mar 2010) $
   64    */
   65   
   66   public class Catalina extends Embedded {
   67   
   68   
   69       // ----------------------------------------------------- Instance Variables
   70   
   71   
   72       /**
   73        * Pathname to the server configuration file.
   74        */
   75       protected String configFile = "conf/server.xml";
   76   
   77       // XXX Should be moved to embedded
   78       /**
   79        * The shared extensions class loader for this server.
   80        */
   81       protected ClassLoader parentClassLoader =
   82           Catalina.class.getClassLoader();
   83   
   84   
   85       /**
   86        * Are we starting a new server?
   87        */
   88       protected boolean starting = false;
   89   
   90   
   91       /**
   92        * Are we stopping an existing server?
   93        */
   94       protected boolean stopping = false;
   95   
   96   
   97       /**
   98        * Use shutdown hook flag.
   99        */
  100       protected boolean useShutdownHook = true;
  101   
  102   
  103       /**
  104        * Shutdown hook.
  105        */
  106       protected Thread shutdownHook = null;
  107   
  108   
  109       // ------------------------------------------------------------- Properties
  110   
  111   
  112       public void setConfig(String file) {
  113           configFile = file;
  114       }
  115   
  116   
  117       public void setConfigFile(String file) {
  118           configFile = file;
  119       }
  120   
  121   
  122       public String getConfigFile() {
  123           return configFile;
  124       }
  125   
  126   
  127       public void setUseShutdownHook(boolean useShutdownHook) {
  128           this.useShutdownHook = useShutdownHook;
  129       }
  130   
  131   
  132       public boolean getUseShutdownHook() {
  133           return useShutdownHook;
  134       }
  135   
  136   
  137       /**
  138        * Set the shared extensions class loader.
  139        *
  140        * @param parentClassLoader The shared extensions class loader.
  141        */
  142       public void setParentClassLoader(ClassLoader parentClassLoader) {
  143   
  144           this.parentClassLoader = parentClassLoader;
  145   
  146       }
  147   
  148   
  149       // ----------------------------------------------------------- Main Program
  150   
  151       /**
  152        * The application main program.
  153        *
  154        * @param args Command line arguments
  155        */
  156       public static void main(String args[]) {
  157           (new Catalina()).process(args);
  158       }
  159   
  160   
  161       /**
  162        * The instance main program.
  163        *
  164        * @param args Command line arguments
  165        */
  166       public void process(String args[]) {
  167   
  168           setAwait(true);
  169           setCatalinaHome();
  170           setCatalinaBase();
  171           try {
  172               if (arguments(args)) {
  173                   if (starting) {
  174                       load(args);
  175                       start();
  176                   } else if (stopping) {
  177                       stopServer();
  178                   }
  179               }
  180           } catch (Exception e) {
  181               e.printStackTrace(System.out);
  182           }
  183       }
  184   
  185   
  186       // ------------------------------------------------------ Protected Methods
  187   
  188   
  189       /**
  190        * Process the specified command line arguments, and return
  191        * <code>true</code> if we should continue processing; otherwise
  192        * return <code>false</code>.
  193        *
  194        * @param args Command line arguments to process
  195        */
  196       protected boolean arguments(String args[]) {
  197   
  198           boolean isConfig = false;
  199   
  200           if (args.length < 1) {
  201               usage();
  202               return (false);
  203           }
  204   
  205           for (int i = 0; i < args.length; i++) {
  206               if (isConfig) {
  207                   configFile = args[i];
  208                   isConfig = false;
  209               } else if (args[i].equals("-config")) {
  210                   isConfig = true;
  211               } else if (args[i].equals("-nonaming")) {
  212                   setUseNaming( false );
  213               } else if (args[i].equals("-help")) {
  214                   usage();
  215                   return (false);
  216               } else if (args[i].equals("start")) {
  217                   starting = true;
  218                   stopping = false;
  219               } else if (args[i].equals("stop")) {
  220                   starting = false;
  221                   stopping = true;
  222               } else {
  223                   usage();
  224                   return (false);
  225               }
  226           }
  227   
  228           return (true);
  229   
  230       }
  231   
  232   
  233       /**
  234        * Return a File object representing our configuration file.
  235        */
  236       protected File configFile() {
  237   
  238           File file = new File(configFile);
  239           if (!file.isAbsolute())
  240               file = new File(System.getProperty("catalina.base"), configFile);
  241           return (file);
  242   
  243       }
  244   
  245   
  246       /**
  247        * Create and configure the Digester we will be using for startup.
  248        */
  249       protected Digester createStartDigester() {
  250           long t1=System.currentTimeMillis();
  251           // Initialize the digester
  252           Digester digester = new Digester();
  253           digester.setValidating(false);
  254           digester.setRulesValidation(true);
  255           HashMap<Class, List<String>> fakeAttributes = new HashMap<Class, List<String>>();
  256           ArrayList<String> attrs = new ArrayList<String>();
  257           attrs.add("className");
  258           fakeAttributes.put(Object.class, attrs);
  259           digester.setFakeAttributes(fakeAttributes);
  260           digester.setClassLoader(StandardServer.class.getClassLoader());
  261   
  262           // Configure the actions we will be using
  263           digester.addObjectCreate("Server",
  264                                    "org.apache.catalina.core.StandardServer",
  265                                    "className");
  266           digester.addSetProperties("Server");
  267           digester.addSetNext("Server",
  268                               "setServer",
  269                               "org.apache.catalina.Server");
  270   
  271           digester.addObjectCreate("Server/GlobalNamingResources",
  272                                    "org.apache.catalina.deploy.NamingResources");
  273           digester.addSetProperties("Server/GlobalNamingResources");
  274           digester.addSetNext("Server/GlobalNamingResources",
  275                               "setGlobalNamingResources",
  276                               "org.apache.catalina.deploy.NamingResources");
  277   
  278           digester.addObjectCreate("Server/Listener",
  279                                    null, // MUST be specified in the element
  280                                    "className");
  281           digester.addSetProperties("Server/Listener");
  282           digester.addSetNext("Server/Listener",
  283                               "addLifecycleListener",
  284                               "org.apache.catalina.LifecycleListener");
  285   
  286           digester.addObjectCreate("Server/Service",
  287                                    "org.apache.catalina.core.StandardService",
  288                                    "className");
  289           digester.addSetProperties("Server/Service");
  290           digester.addSetNext("Server/Service",
  291                               "addService",
  292                               "org.apache.catalina.Service");
  293   
  294           digester.addObjectCreate("Server/Service/Listener",
  295                                    null, // MUST be specified in the element
  296                                    "className");
  297           digester.addSetProperties("Server/Service/Listener");
  298           digester.addSetNext("Server/Service/Listener",
  299                               "addLifecycleListener",
  300                               "org.apache.catalina.LifecycleListener");
  301   
  302           //Executor
  303           digester.addObjectCreate("Server/Service/Executor",
  304                            "org.apache.catalina.core.StandardThreadExecutor",
  305                            "className");
  306           digester.addSetProperties("Server/Service/Executor");
  307   
  308           digester.addSetNext("Server/Service/Executor",
  309                               "addExecutor",
  310                               "org.apache.catalina.Executor");
  311   
  312           
  313           digester.addRule("Server/Service/Connector",
  314                            new ConnectorCreateRule());
  315           digester.addRule("Server/Service/Connector", 
  316                            new SetAllPropertiesRule(new String[]{"executor"}));
  317           digester.addSetNext("Server/Service/Connector",
  318                               "addConnector",
  319                               "org.apache.catalina.connector.Connector");
  320           
  321           
  322   
  323   
  324           digester.addObjectCreate("Server/Service/Connector/Listener",
  325                                    null, // MUST be specified in the element
  326                                    "className");
  327           digester.addSetProperties("Server/Service/Connector/Listener");
  328           digester.addSetNext("Server/Service/Connector/Listener",
  329                               "addLifecycleListener",
  330                               "org.apache.catalina.LifecycleListener");
  331   
  332           // Add RuleSets for nested elements
  333           digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
  334           digester.addRuleSet(new EngineRuleSet("Server/Service/"));
  335           digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
  336           digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
  337           digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
  338           digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
  339   
  340           // When the 'engine' is found, set the parentClassLoader.
  341           digester.addRule("Server/Service/Engine",
  342                            new SetParentClassLoaderRule(parentClassLoader));
  343           digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/"));
  344   
  345           long t2=System.currentTimeMillis();
  346           if (log.isDebugEnabled())
  347               log.debug("Digester for server.xml created " + ( t2-t1 ));
  348           return (digester);
  349   
  350       }
  351   
  352   
  353       /**
  354        * Create and configure the Digester we will be using for shutdown.
  355        */
  356       protected Digester createStopDigester() {
  357   
  358           // Initialize the digester
  359           Digester digester = new Digester();
  360   
  361           // Configure the rules we need for shutting down
  362           digester.addObjectCreate("Server",
  363                                    "org.apache.catalina.core.StandardServer",
  364                                    "className");
  365           digester.addSetProperties("Server");
  366           digester.addSetNext("Server",
  367                               "setServer",
  368                               "org.apache.catalina.Server");
  369   
  370           return (digester);
  371   
  372       }
  373   
  374   
  375       public void stopServer() {
  376           stopServer(null);
  377       }
  378   
  379       public void stopServer(String[] arguments) {
  380   
  381           if (arguments != null) {
  382               arguments(arguments);
  383           }
  384   
  385           if( getServer() == null ) {
  386               // Create and execute our Digester
  387               Digester digester = createStopDigester();
  388               digester.setClassLoader(Thread.currentThread().getContextClassLoader());
  389               File file = configFile();
  390               try {
  391                   InputSource is =
  392                       new InputSource("file://" + file.getAbsolutePath());
  393                   FileInputStream fis = new FileInputStream(file);
  394                   is.setByteStream(fis);
  395                   digester.push(this);
  396                   digester.parse(is);
  397                   fis.close();
  398               } catch (Exception e) {
  399                   log.error("Catalina.stop: ", e);
  400                   System.exit(1);
  401               }
  402           }
  403   
  404           // Stop the existing server
  405           try {
  406               if (getServer().getPort()>0) { 
  407                   String hostAddress = InetAddress.getByName("localhost").getHostAddress();
  408                   Socket socket = new Socket(hostAddress, getServer().getPort());
  409                   OutputStream stream = socket.getOutputStream();
  410                   String shutdown = getServer().getShutdown();
  411                   for (int i = 0; i < shutdown.length(); i++)
  412                       stream.write(shutdown.charAt(i));
  413                   stream.flush();
  414                   stream.close();
  415                   socket.close();
  416               } else {
  417                   log.error(sm.getString("catalina.stopServer"));
  418                   System.exit(1);
  419               }
  420           } catch (IOException e) {
  421               log.error("Catalina.stop: ", e);
  422               System.exit(1);
  423           }
  424   
  425       }
  426   
  427   
  428       /**
  429        * Set the <code>catalina.base</code> System property to the current
  430        * working directory if it has not been set.
  431        * @deprecated Use initDirs()
  432        */
  433       public void setCatalinaBase() {
  434           initDirs();
  435       }
  436   
  437       /**
  438        * Set the <code>catalina.home</code> System property to the current
  439        * working directory if it has not been set.
  440        * @deprecated Use initDirs()
  441        */
  442       public void setCatalinaHome() {
  443           initDirs();
  444       }
  445   
  446       /**
  447        * Start a new server instance.
  448        */
  449       public void load() {
  450   
  451           long t1 = System.nanoTime();
  452   
  453           initDirs();
  454   
  455           // Before digester - it may be needed
  456   
  457           initNaming();
  458   
  459           // Create and execute our Digester
  460           Digester digester = createStartDigester();
  461   
  462           InputSource inputSource = null;
  463           InputStream inputStream = null;
  464           File file = null;
  465           try {
  466               file = configFile();
  467               inputStream = new FileInputStream(file);
  468               inputSource = new InputSource("file://" + file.getAbsolutePath());
  469           } catch (Exception e) {
  470               ;
  471           }
  472           if (inputStream == null) {
  473               try {
  474                   inputStream = getClass().getClassLoader()
  475                       .getResourceAsStream(getConfigFile());
  476                   inputSource = new InputSource
  477                       (getClass().getClassLoader()
  478                        .getResource(getConfigFile()).toString());
  479               } catch (Exception e) {
  480                   ;
  481               }
  482           }
  483   
  484           // This should be included in catalina.jar
  485           // Alternative: don't bother with xml, just create it manually.
  486           if( inputStream==null ) {
  487               try {
  488                   inputStream = getClass().getClassLoader()
  489                   .getResourceAsStream("server-embed.xml");
  490                   inputSource = new InputSource
  491                   (getClass().getClassLoader()
  492                           .getResource("server-embed.xml").toString());
  493               } catch (Exception e) {
  494                   ;
  495               }
  496           }
  497           
  498   
  499           if ((inputStream == null) && (file != null)) {
  500               log.warn("Can't load server.xml from " + file.getAbsolutePath());
  501               if (file.exists() && !file.canRead()) {
  502                   log.warn("Permissions incorrect, read permission is not allowed on the file.");
  503               }
  504               return;
  505           }
  506   
  507           try {
  508               inputSource.setByteStream(inputStream);
  509               digester.push(this);
  510               digester.parse(inputSource);
  511               inputStream.close();
  512           } catch (Exception e) {
  513               log.warn("Catalina.start using "
  514                                  + getConfigFile() + ": " , e);
  515               return;
  516           }
  517   
  518           // Stream redirection
  519           initStreams();
  520   
  521           // Start the new server
  522           if (getServer() instanceof Lifecycle) {
  523               try {
  524                   getServer().initialize();
  525               } catch (LifecycleException e) {
  526                   if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
  527                       throw new java.lang.Error(e);
  528                   else   
  529                       log.error("Catalina.start", e);
  530                   
  531               }
  532           }
  533   
  534           long t2 = System.nanoTime();
  535           if(log.isInfoEnabled())
  536               log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
  537   
  538       }
  539   
  540   
  541       /* 
  542        * Load using arguments
  543        */
  544       public void load(String args[]) {
  545   
  546           try {
  547               if (arguments(args))
  548                   load();
  549           } catch (Exception e) {
  550               e.printStackTrace(System.out);
  551           }
  552       }
  553   
  554       public void create() {
  555   
  556       }
  557   
  558       public void destroy() {
  559   
  560       }
  561   
  562       /**
  563        * Start a new server instance.
  564        */
  565       public void start() {
  566   
  567           if (getServer() == null) {
  568               load();
  569           }
  570   
  571           if (getServer() == null) {
  572               log.fatal("Cannot start server. Server instance is not configured.");
  573               return;
  574           }
  575   
  576           long t1 = System.nanoTime();
  577           
  578           // Start the new server
  579           if (getServer() instanceof Lifecycle) {
  580               try {
  581                   ((Lifecycle) getServer()).start();
  582               } catch (LifecycleException e) {
  583                   log.error("Catalina.start: ", e);
  584               }
  585           }
  586   
  587           long t2 = System.nanoTime();
  588           if(log.isInfoEnabled())
  589               log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
  590   
  591           try {
  592               // Register shutdown hook
  593               if (useShutdownHook) {
  594                   if (shutdownHook == null) {
  595                       shutdownHook = new CatalinaShutdownHook();
  596                   }
  597                   Runtime.getRuntime().addShutdownHook(shutdownHook);
  598                   
  599                   // If JULI is being used, disable JULI's shutdown hook since
  600                   // shutdown hooks run in parallel and log messages may be lost
  601                   // if JULI's hook completes before the CatalinaShutdownHook()
  602                   LogManager logManager = LogManager.getLogManager();
  603                   if (logManager instanceof ClassLoaderLogManager) {
  604                       ((ClassLoaderLogManager) logManager).setUseShutdownHook(
  605                               false);
  606                   }
  607               }
  608           } catch (Throwable t) {
  609               // This will fail on JDK 1.2. Ignoring, as Tomcat can run
  610               // fine without the shutdown hook.
  611           }
  612   
  613           if (await) {
  614               await();
  615               stop();
  616           }
  617   
  618       }
  619   
  620   
  621       /**
  622        * Stop an existing server instance.
  623        */
  624       public void stop() {
  625   
  626           try {
  627               // Remove the ShutdownHook first so that server.stop() 
  628               // doesn't get invoked twice
  629               if (useShutdownHook) {
  630                   Runtime.getRuntime().removeShutdownHook(shutdownHook);
  631   
  632                   // If JULI is being used, re-enable JULI's shutdown to ensure
  633                   // log messages are not lost
  634                   LogManager logManager = LogManager.getLogManager();
  635                   if (logManager instanceof ClassLoaderLogManager) {
  636                       ((ClassLoaderLogManager) logManager).setUseShutdownHook(
  637                               true);
  638                   }
  639               }
  640           } catch (Throwable t) {
  641               // This will fail on JDK 1.2. Ignoring, as Tomcat can run
  642               // fine without the shutdown hook.
  643           }
  644   
  645           // Shut down the server
  646           if (getServer() instanceof Lifecycle) {
  647               try {
  648                   ((Lifecycle) getServer()).stop();
  649               } catch (LifecycleException e) {
  650                   log.error("Catalina.stop", e);
  651               }
  652           }
  653   
  654       }
  655   
  656   
  657       /**
  658        * Await and shutdown.
  659        */
  660       public void await() {
  661   
  662           getServer().await();
  663   
  664       }
  665   
  666   
  667       /**
  668        * Print usage information for this application.
  669        */
  670       protected void usage() {
  671   
  672           System.out.println
  673               ("usage: java org.apache.catalina.startup.Catalina"
  674                + " [ -config {pathname} ]"
  675                + " [ -nonaming ] "
  676                + " { -help | start | stop }");
  677   
  678       }
  679   
  680   
  681       // --------------------------------------- CatalinaShutdownHook Inner Class
  682   
  683       // XXX Should be moved to embedded !
  684       /**
  685        * Shutdown hook which will perform a clean shutdown of Catalina if needed.
  686        */
  687       protected class CatalinaShutdownHook extends Thread {
  688   
  689           public void run() {
  690   
  691               if (getServer() != null) {
  692                   Catalina.this.stop();
  693               }
  694               
  695               // If JULI is used, shut JULI down *after* the server shuts down
  696               // so log messages aren't lost
  697               LogManager logManager = LogManager.getLogManager();
  698               if (logManager instanceof ClassLoaderLogManager) {
  699                   ((ClassLoaderLogManager) logManager).shutdown();
  700               }
  701   
  702           }
  703   
  704       }
  705       
  706       
  707       private static org.apache.juli.logging.Log log=
  708           org.apache.juli.logging.LogFactory.getLog( Catalina.class );
  709   
  710   }
  711   
  712   
  713   // ------------------------------------------------------------ Private Classes
  714   
  715   
  716   /**
  717    * Rule that sets the parent class loader for the top object on the stack,
  718    * which must be a <code>Container</code>.
  719    */
  720   
  721   final class SetParentClassLoaderRule extends Rule {
  722   
  723       public SetParentClassLoaderRule(ClassLoader parentClassLoader) {
  724   
  725           this.parentClassLoader = parentClassLoader;
  726   
  727       }
  728   
  729       ClassLoader parentClassLoader = null;
  730   
  731       public void begin(String namespace, String name, Attributes attributes)
  732           throws Exception {
  733   
  734           if (digester.getLogger().isDebugEnabled())
  735               digester.getLogger().debug("Setting parent class loader");
  736   
  737           Container top = (Container) digester.peek();
  738           top.setParentClassLoader(parentClassLoader);
  739   
  740       }
  741   
  742   
  743   }

Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » startup » [javadoc | source]