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    import java.util.ArrayList;
026    import java.util.Enumeration;
027    import java.util.List;
028    
029    import javax.servlet.http.HttpSession;
030    
031    import org.apache.turbine.Turbine;
032    import org.apache.turbine.TurbineConstants;
033    import org.apache.turbine.modules.Action;
034    import org.apache.turbine.modules.ActionLoader;
035    import org.apache.turbine.services.assemblerbroker.TurbineAssemblerBroker;
036    import org.apache.turbine.services.velocity.VelocityService;
037    import org.apache.turbine.util.RunData;
038    import org.apache.turbine.util.TurbineException;
039    import org.apache.turbine.util.template.TemplateInfo;
040    
041    /**
042     * Handles the Login and Logout actions in the request process
043     * cycle.
044     *
045     * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
046     * @author <a href="mailto:dlr@apache.org">Daniel Rall</a>
047     * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
048     * @version $Id: DefaultLoginValve.java 1078552 2011-03-06 19:58:46Z tv $
049     */
050    public class DefaultLoginValve
051        extends AbstractValve
052    {
053        private ActionLoader actionLoader;
054    
055        /**
056         * Here we can setup objects that are thread safe and can be
057         * reused. We setup the session validator and the access
058         * controller.
059         */
060        public DefaultLoginValve()
061            throws Exception
062        {
063            // empty constructor
064        }
065    
066        /**
067         * Initialize this valve for use in a pipeline.
068         *
069         * @see org.apache.turbine.pipeline.AbstractValve#initialize()
070         */
071        @Override
072        public void initialize() throws Exception
073        {
074            super.initialize();
075    
076            this.actionLoader = (ActionLoader)TurbineAssemblerBroker.getLoader(Action.NAME);
077        }
078    
079        /**
080         * @see org.apache.turbine.Valve#invoke(RunData, ValveContext)
081         */
082        @Override
083        public void invoke(PipelineData pipelineData, ValveContext context)
084            throws IOException, TurbineException
085        {
086            try
087            {
088                process(pipelineData);
089            }
090            catch (Exception e)
091            {
092                throw new TurbineException(e);
093            }
094    
095            // Pass control to the next Valve in the Pipeline
096            context.invokeNext(pipelineData);
097        }
098    
099        /**
100         * Handles user sessions, parsing of the action from the query
101         * string, and access control.
102         *
103         * @param data The run-time data.
104         */
105        protected void process(PipelineData pipelineData)
106            throws Exception
107        {
108            RunData data = getRunData(pipelineData);
109            // Special case for login and logout, this must happen before the
110            // session validator is executed in order either to allow a user to
111            // even login, or to ensure that the session validator gets to
112            // mandate its page selection policy for non-logged in users
113            // after the logout has taken place.
114            String actionName = data.getAction();
115            if (data.hasAction() &&
116                actionName.equalsIgnoreCase
117                (Turbine.getConfiguration().getString(TurbineConstants.ACTION_LOGIN_KEY)) ||
118                actionName.equalsIgnoreCase
119                (Turbine.getConfiguration().getString(TurbineConstants.ACTION_LOGOUT_KEY)))
120            {
121                // If a User is logging in, we should refresh the
122                // session here.  Invalidating session and starting a
123                // new session would seem to be a good method, but I
124                // (JDM) could not get this to work well (it always
125                // required the user to login twice).  Maybe related
126                // to JServ?  If we do not clear out the session, it
127                // is possible a new User may accidently (if they
128                // login incorrectly) continue on with information
129                // associated with the previous User.  Currently the
130                // only keys stored in the session are "turbine.user"
131                // and "turbine.acl".
132                if (actionName.equalsIgnoreCase
133                    (Turbine.getConfiguration().getString(TurbineConstants.ACTION_LOGIN_KEY)))
134                {
135                    @SuppressWarnings("unchecked")
136                    Enumeration<String> names = data.getSession().getAttributeNames();
137                    if (names != null)
138                    {
139                        // copy keys into a new list, so we can clear the session
140                        // and not get ConcurrentModificationException
141                        List<String> nameList = new ArrayList<String>();
142                        while (names.hasMoreElements())
143                        {
144                            nameList.add(names.nextElement());
145                        }
146    
147                        HttpSession session = data.getSession();
148                        for (String name : nameList)
149                        {
150                            try
151                            {
152                                session.removeAttribute(name);
153                            }
154                            catch (IllegalStateException invalidatedSession)
155                            {
156                                break;
157                            }
158                        }
159                    }
160                }
161    
162                actionLoader.exec(pipelineData, data.getAction());
163                cleanupTemplateContext(data);
164                data.setAction(null);
165            }
166        }
167        /**
168         * cleans the Velocity Context if available.
169         *
170         * @param data A RunData Object
171         *
172         * @throws Exception A problem while cleaning out the Template Context occured.
173         */
174        private void cleanupTemplateContext(RunData data)
175        throws Exception
176        {
177            // This is Velocity specific and shouldn't be done here.
178            // But this is a band aid until we get real listeners
179            // here.
180            TemplateInfo ti = data.getTemplateInfo();
181            if (ti != null)
182            {
183                ti.removeTemp(VelocityService.CONTEXT);
184            }
185        }
186    }