View Javadoc

    1   package org.apache.turbine.pipeline;
    2
    3
    4   /*
    5    * Licensed to the Apache Software Foundation (ASF) under one
    6    * or more contributor license agreements.  See the NOTICE file
    7    * distributed with this work for additional information
    8    * regarding copyright ownership.  The ASF licenses this file
    9    * to you under the Apache License, Version 2.0 (the
    10   * "License"); you may not use this file except in compliance
    11   * with the License.  You may obtain a copy of the License at
    12   *
    13   *   http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing,
    16   * software distributed under the License is distributed on an
    17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    18   * KIND, either express or implied.  See the License for the
    19   * specific language governing permissions and limitations
    20   * under the License.
    21   */
    22
    23
    24  import java.io.IOException;
    25
    26  import org.apache.turbine.util.RunData;
    27  import org.apache.turbine.util.TurbineException;
    28
    29  /**
    30   * Flexible implementation of a {@link org.apache.turbine.Pipeline}.
    31   * Originally based on code from Catalina and ideas from Apache httpd.
    32   *
    33   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
    34   * @author <a href="mailto:jvanzyl@zenplex.com">Jason van Zyl</a>
    35   * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
    36   */
    37  public class TurbinePipeline
    38      implements Pipeline, ValveContext
    39  {
    40      /**
    41       * The "Turbine Classic" pipeline.
    42       */
    43      public static String CLASSIC_PIPELINE =
    44          "WEB-INF/conf/turbine-classic-pipeline.xml";
    45
    46      /**
    47       * Name of this pipeline.
    48       */
    49      protected String name;
    50
    51      /**
    52       * The set of Valves associated with this Pipeline.
    53       */
    54      protected Valve[] valves = new Valve[0];
    55
    56      /**
    57       * The per-thread execution state for processing through this
    58       * pipeline.  The actual value is a java.lang.Integer object
    59       * containing the subscript into the <code>values</code> array, or
    60       * a subscript equal to <code>values.length</code> if the basic
    61       * Valve is currently being processed.
    62       */
    63      protected ThreadLocal<Integer> state= new ThreadLocal<Integer>();
    64
    65      /**
    66       * @see org.apache.turbine.Pipeline#initialize()
    67       */
    68      public void initialize()
    69          throws Exception
    70      {
    71          if (state==null)
    72          {
    73              state = new ThreadLocal<Integer>();
    74          }
    75
    76          // Valve implementations are added to this Pipeline using the
    77          // Mapper.
    78
    79          // Initialize the valves
    80          for (int i = 0; i < valves.length; i++)
    81          {
    82              valves[i].initialize();
    83          }
    84      }
    85
    86      /**
    87       * Set the name of this pipeline.
    88       *
    89       * @param name Name of this pipeline.
    90       */
    91      public void setName(String name)
    92      {
    93          this.name = name;
    94      }
    95
    96      /**
    97       * Get the name of this pipeline.
    98       *
    99       * @return String Name of this pipeline.
    100      */
    101     public String getName()
    102     {
    103         return name;
    104     }
    105
    106     /**
    107      * @see org.apache.turbine.Pipeline#addValve(Valve)
    108      */
    109     public void addValve(Valve valve)
    110     {
    111         // Add this Valve to the set associated with this Pipeline
    112         synchronized (valves)
    113         {
    114             Valve[] results = new Valve[valves.length + 1];
    115             System.arraycopy(valves, 0, results, 0, valves.length);
    116             results[valves.length] = valve;
    117             valves = results;
    118         }
    119     }
    120
    121     /**
    122      * @see org.apache.turbine.Pipeline#getValves()
    123      */
    124     public Valve[] getValves()
    125     {
    126         synchronized (valves)
    127         {
    128             Valve[] results = new Valve[valves.length];
    129             System.arraycopy(valves, 0, results, 0, valves.length);
    130             return results;
    131         }
    132     }
    133
    134     /**
    135      * @see org.apache.turbine.Pipeline#removeValve(Valve)
    136      */
    137     public void removeValve(Valve valve)
    138     {
    139         synchronized (valves)
    140         {
    141             // Locate this Valve in our list
    142             int index = -1;
    143             for (int i = 0; i < valves.length; i++)
    144             {
    145                 if (valve == valves[i])
    146                 {
    147                     index = i;
    148                     break;
    149                 }
    150             }
    151             if (index < 0)
    152             {
    153                 return;
    154             }
    155
    156             // Remove this valve from our list
    157             Valve[] results = new Valve[valves.length - 1];
    158             int n = 0;
    159             for (int i = 0; i < valves.length; i++)
    160             {
    161                 if (i == index)
    162                 {
    163                     continue;
    164                 }
    165                 results[n++] = valves[i];
    166             }
    167             valves = results;
    168         }
    169     }
    170
    171     /**
    172      * @see org.apache.turbine.Pipeline#invoke(RunData)
    173      */
    174     public void invoke(PipelineData pipelineData)
    175         throws TurbineException, IOException
    176     {
    177         // Initialize the per-thread state for this thread
    178         state.set(Integer.valueOf(0));
    179
    180         // Invoke the first Valve in this pipeline for this request
    181         invokeNext(pipelineData);
    182     }
    183
    184     /**
    185      * @see org.apache.turbine.ValveContext#invokeNext(RunData)
    186      */
    187     public void invokeNext(PipelineData pipelineData)
    188         throws TurbineException, IOException
    189     {
    190         // Identify the current subscript for the current request thread
    191         Integer current = state.get();
    192         int subscript = current.intValue();
    193
    194         if (subscript < valves.length)
    195         {
    196             // Invoke the requested Valve for the current request
    197             // thread and increment its thread-local state.
    198             state.set(Integer.valueOf(subscript + 1));
    199             valves[subscript].invoke(pipelineData, this);
    200         }
    201     }
    202 }