001 package org.apache.turbine.pipeline; 002 003 004 /* 005 * Licensed to the Apache Software Foundation (ASF) under one 006 * or more contributor license agreements. See the NOTICE file 007 * distributed with this work for additional information 008 * regarding copyright ownership. The ASF licenses this file 009 * to you under the Apache License, Version 2.0 (the 010 * "License"); you may not use this file except in compliance 011 * with the License. You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, 016 * software distributed under the License is distributed on an 017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 018 * KIND, either express or implied. See the License for the 019 * specific language governing permissions and limitations 020 * under the License. 021 */ 022 023 024 import java.io.IOException; 025 026 import org.apache.turbine.util.RunData; 027 import org.apache.turbine.util.TurbineException; 028 029 /** 030 * Flexible implementation of a {@link org.apache.turbine.Pipeline}. 031 * Originally based on code from Catalina and ideas from Apache httpd. 032 * 033 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 034 * @author <a href="mailto:jvanzyl@zenplex.com">Jason van Zyl</a> 035 * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a> 036 */ 037 public class TurbinePipeline 038 implements Pipeline, ValveContext 039 { 040 /** 041 * The "Turbine Classic" pipeline. 042 */ 043 public static String CLASSIC_PIPELINE = 044 "WEB-INF/conf/turbine-classic-pipeline.xml"; 045 046 /** 047 * Name of this pipeline. 048 */ 049 protected String name; 050 051 /** 052 * The set of Valves associated with this Pipeline. 053 */ 054 protected Valve[] valves = new Valve[0]; 055 056 /** 057 * The per-thread execution state for processing through this 058 * pipeline. The actual value is a java.lang.Integer object 059 * containing the subscript into the <code>values</code> array, or 060 * a subscript equal to <code>values.length</code> if the basic 061 * Valve is currently being processed. 062 */ 063 protected ThreadLocal<Integer> state= new ThreadLocal<Integer>(); 064 065 /** 066 * @see org.apache.turbine.Pipeline#initialize() 067 */ 068 public void initialize() 069 throws Exception 070 { 071 if (state==null) 072 { 073 state = new ThreadLocal<Integer>(); 074 } 075 076 // Valve implementations are added to this Pipeline using the 077 // Mapper. 078 079 // Initialize the valves 080 for (int i = 0; i < valves.length; i++) 081 { 082 valves[i].initialize(); 083 } 084 } 085 086 /** 087 * Set the name of this pipeline. 088 * 089 * @param name Name of this pipeline. 090 */ 091 public void setName(String name) 092 { 093 this.name = name; 094 } 095 096 /** 097 * Get the name of this pipeline. 098 * 099 * @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 }