    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    }