Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » catalina » core » [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.core;
   20   
   21   
   22   import java.beans.PropertyChangeListener;
   23   import java.beans.PropertyChangeSupport;
   24   import javax.management.MBeanRegistration;
   25   import javax.management.MBeanServer;
   26   import javax.management.ObjectName;
   27   import org.apache.catalina.Container;
   28   import org.apache.catalina.Engine;
   29   import org.apache.catalina.Lifecycle;
   30   import org.apache.catalina.LifecycleException;
   31   import org.apache.catalina.LifecycleListener;
   32   import org.apache.catalina.Server;
   33   import org.apache.catalina.Service;
   34   import org.apache.catalina.ServerFactory;
   35   import org.apache.catalina.connector.Connector;
   36   import org.apache.catalina.util.LifecycleSupport;
   37   import org.apache.catalina.util.StringManager;
   38   import org.apache.juli.logging.Log;
   39   import org.apache.juli.logging.LogFactory;
   40   import org.apache.tomcat.util.modeler.Registry;
   41   import java.util.ArrayList;
   42   import org.apache.catalina.Executor;
   43   
   44   
   45   /**
   46    * Standard implementation of the <code>Service</code> interface.  The
   47    * associated Container is generally an instance of Engine, but this is
   48    * not required.
   49    *
   50    * @author Craig R. McClanahan
   51    */
   52   
   53   public class StandardService
   54           implements Lifecycle, Service, MBeanRegistration 
   55    {
   56       private static Log log = LogFactory.getLog(StandardService.class);
   57      
   58   
   59       // ----------------------------------------------------- Instance Variables
   60   
   61   
   62       /**
   63        * Descriptive information about this component implementation.
   64        */
   65       private static final String info =
   66           "org.apache.catalina.core.StandardService/1.0";
   67   
   68   
   69       /**
   70        * The name of this service.
   71        */
   72       private String name = null;
   73   
   74   
   75       /**
   76        * The lifecycle event support for this component.
   77        */
   78       private LifecycleSupport lifecycle = new LifecycleSupport(this);
   79   
   80   
   81       /**
   82        * The string manager for this package.
   83        */
   84       private static final StringManager sm =
   85           StringManager.getManager(Constants.Package);
   86   
   87       /**
   88        * The <code>Server</code> that owns this Service, if any.
   89        */
   90       private Server server = null;
   91   
   92       /**
   93        * Has this component been started?
   94        */
   95       private boolean started = false;
   96   
   97   
   98       /**
   99        * The property change support for this component.
  100        */
  101       protected PropertyChangeSupport support = new PropertyChangeSupport(this);
  102   
  103   
  104       /**
  105        * The set of Connectors associated with this Service.
  106        */
  107       protected Connector connectors[] = new Connector[0];
  108       
  109       /**
  110        * 
  111        */
  112       protected ArrayList<Executor> executors = new ArrayList<Executor>();
  113   
  114       /**
  115        * The Container associated with this Service. (In the case of the
  116        * org.apache.catalina.startup.Embedded subclass, this holds the most
  117        * recently added Engine.)
  118        */
  119       protected Container container = null;
  120   
  121   
  122       /**
  123        * Has this component been initialized?
  124        */
  125       protected boolean initialized = false;
  126   
  127   
  128       // ------------------------------------------------------------- Properties
  129   
  130   
  131       /**
  132        * Return the <code>Container</code> that handles requests for all
  133        * <code>Connectors</code> associated with this Service.
  134        */
  135       public Container getContainer() {
  136   
  137           return (this.container);
  138   
  139       }
  140   
  141   
  142       /**
  143        * Set the <code>Container</code> that handles requests for all
  144        * <code>Connectors</code> associated with this Service.
  145        *
  146        * @param container The new Container
  147        */
  148       public void setContainer(Container container) {
  149   
  150           Container oldContainer = this.container;
  151           if ((oldContainer != null) && (oldContainer instanceof Engine))
  152               ((Engine) oldContainer).setService(null);
  153           this.container = container;
  154           if ((this.container != null) && (this.container instanceof Engine))
  155               ((Engine) this.container).setService(this);
  156           if (started && (this.container != null) &&
  157               (this.container instanceof Lifecycle)) {
  158               try {
  159                   ((Lifecycle) this.container).start();
  160               } catch (LifecycleException e) {
  161                   ;
  162               }
  163           }
  164           synchronized (connectors) {
  165               for (int i = 0; i < connectors.length; i++)
  166                   connectors[i].setContainer(this.container);
  167           }
  168           if (started && (oldContainer != null) &&
  169               (oldContainer instanceof Lifecycle)) {
  170               try {
  171                   ((Lifecycle) oldContainer).stop();
  172               } catch (LifecycleException e) {
  173                   ;
  174               }
  175           }
  176   
  177           // Report this property change to interested listeners
  178           support.firePropertyChange("container", oldContainer, this.container);
  179   
  180       }
  181   
  182       public ObjectName getContainerName() {
  183           if( container instanceof ContainerBase ) {
  184               return ((ContainerBase)container).getJmxName();
  185           }
  186           return null;
  187       }
  188   
  189   
  190       /**
  191        * Return descriptive information about this Service implementation and
  192        * the corresponding version number, in the format
  193        * <code>&lt;description&gt;/&lt;version&gt;</code>.
  194        */
  195       public String getInfo() {
  196   
  197           return (info);
  198   
  199       }
  200   
  201   
  202       /**
  203        * Return the name of this Service.
  204        */
  205       public String getName() {
  206   
  207           return (this.name);
  208   
  209       }
  210   
  211   
  212       /**
  213        * Set the name of this Service.
  214        *
  215        * @param name The new service name
  216        */
  217       public void setName(String name) {
  218   
  219           this.name = name;
  220   
  221       }
  222   
  223   
  224       /**
  225        * Return the <code>Server</code> with which we are associated (if any).
  226        */
  227       public Server getServer() {
  228   
  229           return (this.server);
  230   
  231       }
  232   
  233   
  234       /**
  235        * Set the <code>Server</code> with which we are associated (if any).
  236        *
  237        * @param server The server that owns this Service
  238        */
  239       public void setServer(Server server) {
  240   
  241           this.server = server;
  242   
  243       }
  244   
  245   
  246       // --------------------------------------------------------- Public Methods
  247   
  248   
  249       /**
  250        * Add a new Connector to the set of defined Connectors, and associate it
  251        * with this Service's Container.
  252        *
  253        * @param connector The Connector to be added
  254        */
  255       public void addConnector(Connector connector) {
  256   
  257           synchronized (connectors) {
  258               connector.setContainer(this.container);
  259               connector.setService(this);
  260               Connector results[] = new Connector[connectors.length + 1];
  261               System.arraycopy(connectors, 0, results, 0, connectors.length);
  262               results[connectors.length] = connector;
  263               connectors = results;
  264   
  265               if (initialized) {
  266                   try {
  267                       connector.initialize();
  268                   } catch (LifecycleException e) {
  269                       log.error("Connector.initialize", e);
  270                   }
  271               }
  272   
  273               if (started && (connector instanceof Lifecycle)) {
  274                   try {
  275                       ((Lifecycle) connector).start();
  276                   } catch (LifecycleException e) {
  277                       log.error("Connector.start", e);
  278                   }
  279               }
  280   
  281               // Report this property change to interested listeners
  282               support.firePropertyChange("connector", null, connector);
  283           }
  284   
  285       }
  286   
  287       public ObjectName[] getConnectorNames() {
  288           ObjectName results[] = new ObjectName[connectors.length];
  289           for (int i=0; i<results.length; i++) {
  290               results[i] = connectors[i].getObjectName();
  291           }
  292           return results;
  293       }
  294   
  295   
  296       /**
  297        * Add a property change listener to this component.
  298        *
  299        * @param listener The listener to add
  300        */
  301       public void addPropertyChangeListener(PropertyChangeListener listener) {
  302   
  303           support.addPropertyChangeListener(listener);
  304   
  305       }
  306   
  307   
  308       /**
  309        * Find and return the set of Connectors associated with this Service.
  310        */
  311       public Connector[] findConnectors() {
  312   
  313           return (connectors);
  314   
  315       }
  316   
  317   
  318       /**
  319        * Remove the specified Connector from the set associated from this
  320        * Service.  The removed Connector will also be disassociated from our
  321        * Container.
  322        *
  323        * @param connector The Connector to be removed
  324        */
  325       public void removeConnector(Connector connector) {
  326   
  327           synchronized (connectors) {
  328               int j = -1;
  329               for (int i = 0; i < connectors.length; i++) {
  330                   if (connector == connectors[i]) {
  331                       j = i;
  332                       break;
  333                   }
  334               }
  335               if (j < 0)
  336                   return;
  337               if (started && (connectors[j] instanceof Lifecycle)) {
  338                   try {
  339                       ((Lifecycle) connectors[j]).stop();
  340                   } catch (LifecycleException e) {
  341                       log.error("Connector.stop", e);
  342                   }
  343               }
  344               connectors[j].setContainer(null);
  345               connector.setService(null);
  346               int k = 0;
  347               Connector results[] = new Connector[connectors.length - 1];
  348               for (int i = 0; i < connectors.length; i++) {
  349                   if (i != j)
  350                       results[k++] = connectors[i];
  351               }
  352               connectors = results;
  353   
  354               // Report this property change to interested listeners
  355               support.firePropertyChange("connector", connector, null);
  356           }
  357   
  358       }
  359   
  360   
  361       /**
  362        * Remove a property change listener from this component.
  363        *
  364        * @param listener The listener to remove
  365        */
  366       public void removePropertyChangeListener(PropertyChangeListener listener) {
  367   
  368           support.removePropertyChangeListener(listener);
  369   
  370       }
  371   
  372   
  373       /**
  374        * Return a String representation of this component.
  375        */
  376       public String toString() {
  377   
  378           StringBuffer sb = new StringBuffer("StandardService[");
  379           sb.append(getName());
  380           sb.append("]");
  381           return (sb.toString());
  382   
  383       }
  384   
  385   
  386       // ------------------------------------------------------ Lifecycle Methods
  387   
  388   
  389       /**
  390        * Add a LifecycleEvent listener to this component.
  391        *
  392        * @param listener The listener to add
  393        */
  394       public void addLifecycleListener(LifecycleListener listener) {
  395   
  396           lifecycle.addLifecycleListener(listener);
  397   
  398       }
  399   
  400   
  401       /**
  402        * Get the lifecycle listeners associated with this lifecycle. If this 
  403        * Lifecycle has no listeners registered, a zero-length array is returned.
  404        */
  405       public LifecycleListener[] findLifecycleListeners() {
  406   
  407           return lifecycle.findLifecycleListeners();
  408   
  409       }
  410   
  411   
  412       /**
  413        * Remove a LifecycleEvent listener from this component.
  414        *
  415        * @param listener The listener to remove
  416        */
  417       public void removeLifecycleListener(LifecycleListener listener) {
  418   
  419           lifecycle.removeLifecycleListener(listener);
  420   
  421       }
  422       
  423       /**
  424        * Adds a named executor to the service
  425        * @param ex Executor
  426        */
  427       public void addExecutor(Executor ex) {
  428           synchronized (executors) {
  429               if (!executors.contains(ex)) {
  430                   executors.add(ex);
  431                   if (started)
  432                       try {
  433                           ex.start();
  434                       } catch (LifecycleException x) {
  435                           log.error("Executor.start", x);
  436                       }
  437               }
  438           }
  439       }
  440   
  441       /**
  442        * Retrieves all executors
  443        * @return Executor[]
  444        */
  445       public Executor[] findExecutors() {
  446           synchronized (executors) {
  447               Executor[] arr = new Executor[executors.size()];
  448               executors.toArray(arr);
  449               return arr;
  450           }
  451       }
  452   
  453       /**
  454        * Retrieves executor by name, null if not found
  455        * @param name String
  456        * @return Executor
  457        */
  458       public Executor getExecutor(String name) {
  459           synchronized (executors) {
  460               for (int i = 0; i < executors.size(); i++) {
  461                   if (name.equals(executors.get(i).getName()))
  462                       return executors.get(i);
  463               }
  464           }
  465           return null;
  466       }
  467   
  468       /**
  469        * Removes an executor from the service
  470        * @param ex Executor
  471        */
  472       public void removeExecutor(Executor ex) {
  473           synchronized (executors) {
  474               if ( executors.remove(ex) && started ) {
  475                   try {
  476                       ex.stop();
  477                   } catch (LifecycleException e) {
  478                       log.error("Executor.stop", e);
  479                   }
  480               }
  481           }
  482       }
  483   
  484   
  485   
  486       /**
  487        * Prepare for the beginning of active use of the public methods of this
  488        * component.  This method should be called before any of the public
  489        * methods of this component are utilized.  It should also send a
  490        * LifecycleEvent of type START_EVENT to any registered listeners.
  491        *
  492        * @exception LifecycleException if this component detects a fatal error
  493        *  that prevents this component from being used
  494        */
  495       public void start() throws LifecycleException {
  496   
  497           // Validate and update our current component state
  498           if (started) {
  499               if (log.isInfoEnabled()) {
  500                   log.info(sm.getString("standardService.start.started"));
  501               }
  502               return;
  503           }
  504           
  505           if( ! initialized )
  506               init(); 
  507   
  508           // Notify our interested LifecycleListeners
  509           lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
  510           if(log.isInfoEnabled())
  511               log.info(sm.getString("standardService.start.name", this.name));
  512           lifecycle.fireLifecycleEvent(START_EVENT, null);
  513           started = true;
  514   
  515           // Start our defined Container first
  516           if (container != null) {
  517               synchronized (container) {
  518                   if (container instanceof Lifecycle) {
  519                       ((Lifecycle) container).start();
  520                   }
  521               }
  522           }
  523   
  524           synchronized (executors) {
  525               for ( int i=0; i<executors.size(); i++ ) {
  526                   executors.get(i).start();
  527               }
  528           }
  529   
  530           // Start our defined Connectors second
  531           synchronized (connectors) {
  532               for (int i = 0; i < connectors.length; i++) {
  533                   if (connectors[i] instanceof Lifecycle)
  534                       ((Lifecycle) connectors[i]).start();
  535               }
  536           }
  537           
  538           // Notify our interested LifecycleListeners
  539           lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
  540   
  541       }
  542   
  543   
  544       /**
  545        * Gracefully terminate the active use of the public methods of this
  546        * component.  This method should be the last one called on a given
  547        * instance of this component.  It should also send a LifecycleEvent
  548        * of type STOP_EVENT to any registered listeners.
  549        *
  550        * @exception LifecycleException if this component detects a fatal error
  551        *  that needs to be reported
  552        */
  553       public void stop() throws LifecycleException {
  554   
  555           // Validate and update our current component state
  556           if (!started) {
  557               return;
  558           }
  559   
  560           // Notify our interested LifecycleListeners
  561           lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
  562   
  563           // Stop our defined Connectors first
  564           synchronized (connectors) {
  565               for (int i = 0; i < connectors.length; i++) {
  566                   connectors[i].pause();
  567               }
  568           }
  569   
  570           // Heuristic: Sleep for a while to ensure pause of the connector
  571           try {
  572               Thread.sleep(1000);
  573           } catch (InterruptedException e) {
  574               // Ignore
  575           }
  576   
  577           lifecycle.fireLifecycleEvent(STOP_EVENT, null);
  578           if(log.isInfoEnabled())
  579               log.info
  580                   (sm.getString("standardService.stop.name", this.name));
  581           started = false;
  582   
  583           // Stop our defined Container second
  584           if (container != null) {
  585               synchronized (container) {
  586                   if (container instanceof Lifecycle) {
  587                       ((Lifecycle) container).stop();
  588                   }
  589               }
  590           }
  591           // FIXME pero -- Why container stop first? KeepAlive connetions can send request! 
  592           // Stop our defined Connectors first
  593           synchronized (connectors) {
  594               for (int i = 0; i < connectors.length; i++) {
  595                   if (connectors[i] instanceof Lifecycle)
  596                       ((Lifecycle) connectors[i]).stop();
  597               }
  598           }
  599   
  600           synchronized (executors) {
  601               for ( int i=0; i<executors.size(); i++ ) {
  602                   executors.get(i).stop();
  603               }
  604           }
  605   
  606           if( oname==controller ) {
  607               // we registered ourself on init().
  608               // That should be the typical case - this object is just for
  609               // backward compat, nobody should bother to load it explicitely
  610               Registry.getRegistry(null, null).unregisterComponent(oname);
  611               Executor[] executors = findExecutors();
  612               for (int i = 0; i < executors.length; i++) {
  613                   try {
  614                       ObjectName executorObjectName = 
  615                           new ObjectName(domain + ":type=Executor,name=" + executors[i].getName());
  616                       Registry.getRegistry(null, null).unregisterComponent(executorObjectName);
  617                   } catch (Exception e) {
  618                       // Ignore (invalid ON, which cannot happen)
  619                   }
  620               }
  621           }
  622           
  623   
  624           // Notify our interested LifecycleListeners
  625           lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
  626   
  627       }
  628   
  629   
  630       /**
  631        * Invoke a pre-startup initialization. This is used to allow connectors
  632        * to bind to restricted ports under Unix operating environments.
  633        */
  634       public void initialize()
  635               throws LifecycleException
  636       {
  637           // Service shouldn't be used with embeded, so it doesn't matter
  638           if (initialized) {
  639               if(log.isInfoEnabled())
  640                   log.info(sm.getString("standardService.initialize.initialized"));
  641               return;
  642           }
  643           initialized = true;
  644   
  645           if( oname==null ) {
  646               try {
  647                   // Hack - Server should be deprecated...
  648                   Container engine=this.getContainer();
  649                   domain=engine.getName();
  650                   oname=new ObjectName(domain + ":type=Service,serviceName="+name);
  651                   this.controller=oname;
  652                   Registry.getRegistry(null, null)
  653                       .registerComponent(this, oname, null);
  654                   
  655                   Executor[] executors = findExecutors();
  656                   for (int i = 0; i < executors.length; i++) {
  657                       ObjectName executorObjectName = 
  658                           new ObjectName(domain + ":type=Executor,name=" + executors[i].getName());
  659                       Registry.getRegistry(null, null)
  660                           .registerComponent(executors[i], executorObjectName, null);
  661                   }
  662                   
  663               } catch (Exception e) {
  664                   log.error(sm.getString("standardService.register.failed",domain),e);
  665               }
  666               
  667               
  668           }
  669           if( server==null ) {
  670               // Register with the server 
  671               // HACK: ServerFactory should be removed...
  672               
  673               ServerFactory.getServer().addService(this);
  674           }
  675                  
  676   
  677           // Initialize our defined Connectors
  678           synchronized (connectors) {
  679                   for (int i = 0; i < connectors.length; i++) {
  680                       connectors[i].initialize();
  681                   }
  682           }
  683       }
  684       
  685       public void destroy() throws LifecycleException {
  686           if( started ) stop();
  687           // FIXME unregister should be here probably -- stop doing that ?
  688       }
  689   
  690       public void init() {
  691           try {
  692               initialize();
  693           } catch( Throwable t ) {
  694               log.error(sm.getString("standardService.initialize.failed",domain),t);
  695           }
  696       }
  697   
  698       protected String type;
  699       protected String domain;
  700       protected String suffix;
  701       protected ObjectName oname;
  702       protected ObjectName controller;
  703       protected MBeanServer mserver;
  704   
  705       public ObjectName getObjectName() {
  706           return oname;
  707       }
  708   
  709       public String getDomain() {
  710           return domain;
  711       }
  712   
  713       public ObjectName preRegister(MBeanServer server,
  714                                     ObjectName name) throws Exception {
  715           oname=name;
  716           mserver=server;
  717           domain=name.getDomain();
  718           return name;
  719       }
  720   
  721       public void postRegister(Boolean registrationDone) {
  722       }
  723   
  724       public void preDeregister() throws Exception {
  725       }
  726   
  727       public void postDeregister() {
  728       }
  729   
  730   }

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