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<>();
66  
67      /**
68       * The per-thread execution state for processing through this pipeline.
69       */
70      private ThreadLocal<Iterator<Valve>> state = new ThreadLocal<>();
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<>(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 }