View Javadoc

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