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.util.ArrayList;
   23   
   24   import javax.management.ObjectName;
   25   
   26   import org.apache.catalina.Contained;
   27   import org.apache.catalina.Container;
   28   import org.apache.catalina.Lifecycle;
   29   import org.apache.catalina.LifecycleException;
   30   import org.apache.catalina.LifecycleListener;
   31   import org.apache.catalina.Pipeline;
   32   import org.apache.catalina.Valve;
   33   import org.apache.catalina.util.LifecycleSupport;
   34   import org.apache.catalina.util.StringManager;
   35   import org.apache.catalina.valves.ValveBase;
   36   import org.apache.juli.logging.Log;
   37   import org.apache.juli.logging.LogFactory;
   38   import org.apache.tomcat.util.modeler.Registry;
   39   
   40   
   41   /**
   42    * Standard implementation of a processing <b>Pipeline</b> that will invoke
   43    * a series of Valves that have been configured to be called in order.  This
   44    * implementation can be used for any type of Container.
   45    *
   46    * <b>IMPLEMENTATION WARNING</b> - This implementation assumes that no
   47    * calls to <code>addValve()</code> or <code>removeValve</code> are allowed
   48    * while a request is currently being processed.  Otherwise, the mechanism
   49    * by which per-thread state is maintained will need to be modified.
   50    *
   51    * @author Craig R. McClanahan
   52    */
   53   
   54   public class StandardPipeline
   55       implements Pipeline, Contained, Lifecycle 
   56    {
   57   
   58       private static Log log = LogFactory.getLog(StandardPipeline.class);
   59   
   60       // ----------------------------------------------------------- Constructors
   61   
   62   
   63       /**
   64        * Construct a new StandardPipeline instance with no associated Container.
   65        */
   66       public StandardPipeline() {
   67   
   68           this(null);
   69   
   70       }
   71   
   72   
   73       /**
   74        * Construct a new StandardPipeline instance that is associated with the
   75        * specified Container.
   76        *
   77        * @param container The container we should be associated with
   78        */
   79       public StandardPipeline(Container container) {
   80   
   81           super();
   82           setContainer(container);
   83   
   84       }
   85   
   86   
   87       // ----------------------------------------------------- Instance Variables
   88   
   89   
   90       /**
   91        * The basic Valve (if any) associated with this Pipeline.
   92        */
   93       protected Valve basic = null;
   94   
   95   
   96       /**
   97        * The Container with which this Pipeline is associated.
   98        */
   99       protected Container container = null;
  100   
  101   
  102       /**
  103        * Descriptive information about this implementation.
  104        */
  105       protected String info = "org.apache.catalina.core.StandardPipeline/1.0";
  106   
  107   
  108       /**
  109        * The lifecycle event support for this component.
  110        */
  111       protected LifecycleSupport lifecycle = new LifecycleSupport(this);
  112   
  113   
  114       /**
  115        * The string manager for this package.
  116        */
  117       protected static StringManager sm =
  118           StringManager.getManager(Constants.Package);
  119   
  120   
  121       /**
  122        * Has this component been started yet?
  123        */
  124       protected boolean started = false;
  125   
  126   
  127       /**
  128        * The first valve associated with this Pipeline.
  129        */
  130       protected Valve first = null;
  131   
  132   
  133       // --------------------------------------------------------- Public Methods
  134   
  135   
  136       /**
  137        * Return descriptive information about this implementation class.
  138        */
  139       public String getInfo() {
  140   
  141           return (this.info);
  142   
  143       }
  144   
  145   
  146       // ------------------------------------------------------ Contained Methods
  147   
  148   
  149       /**
  150        * Return the Container with which this Pipeline is associated.
  151        */
  152       public Container getContainer() {
  153   
  154           return (this.container);
  155   
  156       }
  157   
  158   
  159       /**
  160        * Set the Container with which this Pipeline is associated.
  161        *
  162        * @param container The new associated container
  163        */
  164       public void setContainer(Container container) {
  165   
  166           this.container = container;
  167   
  168       }
  169   
  170   
  171       // ------------------------------------------------------ Lifecycle Methods
  172   
  173   
  174       /**
  175        * Add a lifecycle event listener to this component.
  176        *
  177        * @param listener The listener to add
  178        */
  179       public void addLifecycleListener(LifecycleListener listener) {
  180   
  181           lifecycle.addLifecycleListener(listener);
  182   
  183       }
  184   
  185   
  186       /**
  187        * Get the lifecycle listeners associated with this lifecycle. If this 
  188        * Lifecycle has no listeners registered, a zero-length array is returned.
  189        */
  190       public LifecycleListener[] findLifecycleListeners() {
  191   
  192           return lifecycle.findLifecycleListeners();
  193   
  194       }
  195   
  196   
  197       /**
  198        * Remove a lifecycle event listener from this component.
  199        *
  200        * @param listener The listener to remove
  201        */
  202       public void removeLifecycleListener(LifecycleListener listener) {
  203   
  204           lifecycle.removeLifecycleListener(listener);
  205   
  206       }
  207   
  208       /**
  209        * Prepare for active use of the public methods of this Component.
  210        *
  211        * @exception LifecycleException if this component detects a fatal error
  212        *  that prevents it from being started
  213        */
  214       public synchronized void start() throws LifecycleException {
  215   
  216           // Validate and update our current component state
  217           if (started)
  218               throw new LifecycleException
  219                   (sm.getString("standardPipeline.alreadyStarted"));
  220   
  221           // Notify our interested LifecycleListeners
  222           lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
  223   
  224           started = true;
  225   
  226           // Start the Valves in our pipeline (including the basic), if any
  227           Valve current = first;
  228           if (current == null) {
  229           	current = basic;
  230           }
  231           while (current != null) {
  232               if (current instanceof Lifecycle)
  233                   ((Lifecycle) current).start();
  234               registerValve(current);
  235           	current = current.getNext();
  236           }
  237   
  238           // Notify our interested LifecycleListeners
  239           lifecycle.fireLifecycleEvent(START_EVENT, null);
  240   
  241           // Notify our interested LifecycleListeners
  242           lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
  243   
  244       }
  245   
  246   
  247       /**
  248        * Gracefully shut down active use of the public methods of this Component.
  249        *
  250        * @exception LifecycleException if this component detects a fatal error
  251        *  that needs to be reported
  252        */
  253       public synchronized void stop() throws LifecycleException {
  254   
  255           // Validate and update our current component state
  256           if (!started)
  257               throw new LifecycleException
  258                   (sm.getString("standardPipeline.notStarted"));
  259   
  260           // Notify our interested LifecycleListeners
  261           lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
  262   
  263           // Notify our interested LifecycleListeners
  264           lifecycle.fireLifecycleEvent(STOP_EVENT, null);
  265           started = false;
  266   
  267           // Stop the Valves in our pipeline (including the basic), if any
  268           Valve current = first;
  269           if (current == null) {
  270           	current = basic;
  271           }
  272           while (current != null) {
  273               if (current instanceof Lifecycle)
  274                   ((Lifecycle) current).stop();
  275               unregisterValve(current);
  276           	current = current.getNext();
  277           }
  278   
  279           // Notify our interested LifecycleListeners
  280           lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
  281       }
  282   
  283       private void registerValve(Valve valve) {
  284   
  285           if( valve instanceof ValveBase &&
  286                   ((ValveBase)valve).getObjectName()==null ) {
  287               try {
  288                   
  289                   String domain=((ContainerBase)container).getDomain();
  290                   if( container instanceof StandardContext ) {
  291                       domain=((StandardContext)container).getEngineName();
  292                   }
  293                   if( container instanceof StandardWrapper) {
  294                       Container ctx=((StandardWrapper)container).getParent();
  295                       domain=((StandardContext)ctx).getEngineName();
  296                   }
  297                   ObjectName vname=((ValveBase)valve).createObjectName(
  298                           domain,
  299                           ((ContainerBase)container).getJmxName());
  300                   if( vname != null ) {
  301                       ((ValveBase)valve).setObjectName(vname);
  302                       Registry.getRegistry(null, null).registerComponent
  303                           (valve, vname, valve.getClass().getName());
  304                       ((ValveBase)valve).setController
  305                           (((ContainerBase)container).getJmxName());
  306                   }
  307               } catch( Throwable t ) {
  308                   log.info( "Can't register valve " + valve , t );
  309               }
  310           }
  311       }
  312       
  313       private void unregisterValve(Valve valve) {
  314           if( valve instanceof ValveBase ) {
  315               try {
  316                   ValveBase vb=(ValveBase)valve;
  317                   if( vb.getController()!=null &&
  318                           vb.getController() == 
  319                           ((ContainerBase)container).getJmxName() ) {
  320                       
  321                       ObjectName vname=vb.getObjectName();
  322                       Registry.getRegistry(null, null).getMBeanServer()
  323                           .unregisterMBean(vname);
  324                       ((ValveBase)valve).setObjectName(null);
  325                   }
  326               } catch( Throwable t ) {
  327                   log.info( "Can't unregister valve " + valve , t );
  328               }
  329           }
  330       }    
  331   
  332       // ------------------------------------------------------- Pipeline Methods
  333   
  334   
  335       /**
  336        * <p>Return the Valve instance that has been distinguished as the basic
  337        * Valve for this Pipeline (if any).
  338        */
  339       public Valve getBasic() {
  340   
  341           return (this.basic);
  342   
  343       }
  344   
  345   
  346       /**
  347        * <p>Set the Valve instance that has been distinguished as the basic
  348        * Valve for this Pipeline (if any).  Prioer to setting the basic Valve,
  349        * the Valve's <code>setContainer()</code> will be called, if it
  350        * implements <code>Contained</code>, with the owning Container as an
  351        * argument.  The method may throw an <code>IllegalArgumentException</code>
  352        * if this Valve chooses not to be associated with this Container, or
  353        * <code>IllegalStateException</code> if it is already associated with
  354        * a different Container.</p>
  355        *
  356        * @param valve Valve to be distinguished as the basic Valve
  357        */
  358       public void setBasic(Valve valve) {
  359   
  360           // Change components if necessary
  361           Valve oldBasic = this.basic;
  362           if (oldBasic == valve)
  363               return;
  364   
  365           // Stop the old component if necessary
  366           if (oldBasic != null) {
  367               if (started && (oldBasic instanceof Lifecycle)) {
  368                   try {
  369                       ((Lifecycle) oldBasic).stop();
  370                   } catch (LifecycleException e) {
  371                       log.error("StandardPipeline.setBasic: stop", e);
  372                   }
  373               }
  374               if (oldBasic instanceof Contained) {
  375                   try {
  376                       ((Contained) oldBasic).setContainer(null);
  377                   } catch (Throwable t) {
  378                       ;
  379                   }
  380               }
  381           }
  382   
  383           // Start the new component if necessary
  384           if (valve == null)
  385               return;
  386           if (valve instanceof Contained) {
  387               ((Contained) valve).setContainer(this.container);
  388           }
  389           if (valve instanceof Lifecycle) {
  390               try {
  391                   ((Lifecycle) valve).start();
  392               } catch (LifecycleException e) {
  393                   log.error("StandardPipeline.setBasic: start", e);
  394                   return;
  395               }
  396           }
  397   
  398           // Update the pipeline
  399           Valve current = first;
  400           while (current != null) {
  401           	if (current.getNext() == oldBasic) {
  402           		current.setNext(valve);
  403           		break;
  404           	}
  405           	current = current.getNext();
  406           }
  407           
  408           this.basic = valve;
  409   
  410       }
  411   
  412   
  413       /**
  414        * <p>Add a new Valve to the end of the pipeline associated with this
  415        * Container.  Prior to adding the Valve, the Valve's
  416        * <code>setContainer()</code> method will be called, if it implements
  417        * <code>Contained</code>, with the owning Container as an argument.
  418        * The method may throw an
  419        * <code>IllegalArgumentException</code> if this Valve chooses not to
  420        * be associated with this Container, or <code>IllegalStateException</code>
  421        * if it is already associated with a different Container.</p>
  422        *
  423        * @param valve Valve to be added
  424        *
  425        * @exception IllegalArgumentException if this Container refused to
  426        *  accept the specified Valve
  427        * @exception IllegalArgumentException if the specifie Valve refuses to be
  428        *  associated with this Container
  429        * @exception IllegalStateException if the specified Valve is already
  430        *  associated with a different Container
  431        */
  432       public void addValve(Valve valve) {
  433       
  434           // Validate that we can add this Valve
  435           if (valve instanceof Contained)
  436               ((Contained) valve).setContainer(this.container);
  437   
  438           // Start the new component if necessary
  439           if (started) {
  440               if (valve instanceof Lifecycle) {
  441                   try {
  442                       ((Lifecycle) valve).start();
  443                   } catch (LifecycleException e) {
  444                       log.error("StandardPipeline.addValve: start: ", e);
  445                   }
  446               }
  447               // Register the newly added valve
  448               registerValve(valve);
  449           }
  450   
  451           // Add this Valve to the set associated with this Pipeline
  452           if (first == null) {
  453           	first = valve;
  454           	valve.setNext(basic);
  455           } else {
  456               Valve current = first;
  457               while (current != null) {
  458   				if (current.getNext() == basic) {
  459   					current.setNext(valve);
  460   					valve.setNext(basic);
  461   					break;
  462   				}
  463   				current = current.getNext();
  464   			}
  465           }
  466   
  467       }
  468   
  469   
  470       /**
  471        * Return the set of Valves in the pipeline associated with this
  472        * Container, including the basic Valve (if any).  If there are no
  473        * such Valves, a zero-length array is returned.
  474        */
  475       public Valve[] getValves() {
  476   
  477       	ArrayList valveList = new ArrayList();
  478           Valve current = first;
  479           if (current == null) {
  480           	current = basic;
  481           }
  482           while (current != null) {
  483           	valveList.add(current);
  484           	current = current.getNext();
  485           }
  486   
  487           return ((Valve[]) valveList.toArray(new Valve[0]));
  488   
  489       }
  490   
  491       public ObjectName[] getValveObjectNames() {
  492   
  493       	ArrayList valveList = new ArrayList();
  494           Valve current = first;
  495           if (current == null) {
  496           	current = basic;
  497           }
  498           while (current != null) {
  499           	if (current instanceof ValveBase) {
  500           		valveList.add(((ValveBase) current).getObjectName());
  501           	}
  502           	current = current.getNext();
  503           }
  504   
  505           return ((ObjectName[]) valveList.toArray(new ObjectName[0]));
  506   
  507       }
  508   
  509       /**
  510        * Remove the specified Valve from the pipeline associated with this
  511        * Container, if it is found; otherwise, do nothing.  If the Valve is
  512        * found and removed, the Valve's <code>setContainer(null)</code> method
  513        * will be called if it implements <code>Contained</code>.
  514        *
  515        * @param valve Valve to be removed
  516        */
  517       public void removeValve(Valve valve) {
  518   
  519           Valve current;
  520           if(first == valve) {
  521               first = first.getNext();
  522               current = null;
  523           } else {
  524               current = first;
  525           }
  526           while (current != null) {
  527               if (current.getNext() == valve) {
  528                   current.setNext(valve.getNext());
  529                   break;
  530               }
  531               current = current.getNext();
  532           }
  533   
  534           if (first == basic) first = null;
  535   
  536           if (valve instanceof Contained)
  537               ((Contained) valve).setContainer(null);
  538   
  539           // Stop this valve if necessary
  540           if (started) {
  541               if (valve instanceof Lifecycle) {
  542                   try {
  543                       ((Lifecycle) valve).stop();
  544                   } catch (LifecycleException e) {
  545                       log.error("StandardPipeline.removeValve: stop: ", e);
  546                   }
  547               }
  548               // Unregister the removed valave
  549               unregisterValve(valve);
  550           }
  551       
  552       }
  553   
  554   
  555       public Valve getFirst() {
  556           if (first != null) {
  557               return first;
  558           } else {
  559               return basic;
  560           }
  561       }
  562   
  563   
  564   }

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