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.annotation.AnnotationProcessor;
    27  import org.apache.turbine.util.TurbineException;
    28
    29  /**
    30   * Flexible implementation of a {@link org.apache.turbine.pipeline.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 final 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.Pipeline#initialize()
    67       */
    68      @Override
    69      public void initialize()
    70          throws Exception
    71      {
    72          if (state==null)
    73          {
    74              state = new ThreadLocal<Integer>();
    75          }
    76
    77          // Valve implementations are added to this Pipeline using the
    78          // Mapper.
    79
    80          // Initialize the valves
    81          for (int i = 0; i < valves.length; i++)
    82          {
    83              AnnotationProcessor.process(valves[i]);
    84              valves[i].initialize();
    85          }
    86      }
    87
    88      /**
    89       * Set the name of this pipeline.
    90       *
    91       * @param name Name of this pipeline.
    92       */
    93      public void setName(String name)
    94      {
    95          this.name = name;
    96      }
    97
    98      /**
    99       * Get the name of this pipeline.
    100      *
    101      * @return String Name of this pipeline.
    102      */
    103     public String getName()
    104     {
    105         return name;
    106     }
    107
    108     /**
    109      * @see org.apache.turbine.pipeline.Pipeline#addValve(Valve)
    110      */
    111     @Override
    112     public void addValve(Valve valve)
    113     {
    114         // Add this Valve to the set associated with this Pipeline
    115         synchronized (valves)
    116         {
    117             Valve[] results = new Valve[valves.length + 1];
    118             System.arraycopy(valves, 0, results, 0, valves.length);
    119             results[valves.length] = valve;
    120             valves = results;
    121         }
    122     }
    123
    124     /**
    125      * @see org.apache.turbine.pipeline.Pipeline#getValves()
    126      */
    127     @Override
    128     public Valve[] getValves()
    129     {
    130         synchronized (valves)
    131         {
    132             Valve[] results = new Valve[valves.length];
    133             System.arraycopy(valves, 0, results, 0, valves.length);
    134             return results;
    135         }
    136     }
    137
    138     /**
    139      * @see org.apache.turbine.pipeline.Pipeline#removeValve(Valve)
    140      */
    141     @Override
    142     public void removeValve(Valve valve)
    143     {
    144         synchronized (valves)
    145         {
    146             // Locate this Valve in our list
    147             int index = -1;
    148             for (int i = 0; i < valves.length; i++)
    149             {
    150                 if (valve == valves[i])
    151                 {
    152                     index = i;
    153                     break;
    154                 }
    155             }
    156             if (index < 0)
    157             {
    158                 return;
    159             }
    160
    161             // Remove this valve from our list
    162             Valve[] results = new Valve[valves.length - 1];
    163             int n = 0;
    164             for (int i = 0; i < valves.length; i++)
    165             {
    166                 if (i == index)
    167                 {
    168                     continue;
    169                 }
    170                 results[n++] = valves[i];
    171             }
    172             valves = results;
    173         }
    174     }
    175
    176     /**
    177      * @see org.apache.turbine.pipeline.Pipeline#invoke(PipelineData)
    178      */
    179     @Override
    180     public void invoke(PipelineData pipelineData)
    181         throws TurbineException, IOException
    182     {
    183         // Initialize the per-thread state for this thread
    184         state.set(Integer.valueOf(0));
    185
    186         // Invoke the first Valve in this pipeline for this request
    187         invokeNext(pipelineData);
    188     }
    189
    190     /**
    191      * @see org.apache.turbine.pipeline.ValveContext#invokeNext(PipelineData)
    192      */
    193     @Override
    194     public void invokeNext(PipelineData pipelineData)
    195         throws TurbineException, IOException
    196     {
    197         // Identify the current subscript for the current request thread
    198         Integer current = state.get();
    199         int subscript = current.intValue();
    200
    201         if (subscript < valves.length)
    202         {
    203             // Invoke the requested Valve for the current request
    204             // thread and increment its thread-local state.
    205             state.set(Integer.valueOf(subscript + 1));
    206             valves[subscript].invoke(pipelineData, this);
    207         }
    208     }
    209 }