    001package 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
    024import java.io.IOException;
    025import java.util.ArrayList;
    026import java.util.Enumeration;
    027import java.util.List;
    028
    029import javax.servlet.http.HttpSession;
    030
    031import org.apache.turbine.TurbineConstants;
    032import org.apache.turbine.annotation.TurbineConfiguration;
    033import org.apache.turbine.annotation.TurbineLoader;
    034import org.apache.turbine.modules.Action;
    035import org.apache.turbine.modules.ActionLoader;
    036import org.apache.turbine.services.velocity.VelocityService;
    037import org.apache.turbine.util.RunData;
    038import org.apache.turbine.util.TurbineException;
    039import 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 1773378 2016-12-09 13:19:59Z tv $
    049 */
    050public class DefaultLoginValve
    051    extends AbstractValve
    052{
    053    /** Injected loader instance */
    054    @TurbineLoader( Action.class )
    055    private ActionLoader actionLoader;
    056
    057    @TurbineConfiguration( TurbineConstants.ACTION_LOGIN_KEY )
    058    private String actionLogin;
    059
    060    @TurbineConfiguration( TurbineConstants.ACTION_LOGOUT_KEY )
    061    private String actionLogout;
    062
    063    /**
    064     * @see org.apache.turbine.pipeline.Valve#invoke(PipelineData, ValveContext)
    065     */
    066    @Override
    067    public void invoke(PipelineData pipelineData, ValveContext context)
    068        throws IOException, TurbineException
    069    {
    070        try
    071        {
    072            process(pipelineData);
    073        }
    074        catch (Exception e)
    075        {
    076            throw new TurbineException(e);
    077        }
    078
    079        // Pass control to the next Valve in the Pipeline
    080        context.invokeNext(pipelineData);
    081    }
    082
    083    /**
    084     * Handles user sessions, parsing of the action from the query
    085     * string, and access control.
    086     *
    087     * @param pipelineData The run-time data.
    088     *
    089     * @throws Exception if executing the action fails
    090     */
    091    protected void process(PipelineData pipelineData)
    092        throws Exception
    093    {
    094        RunData data = getRunData(pipelineData);
    095        // Special case for login and logout, this must happen before the
    096        // session validator is executed in order either to allow a user to
    097        // even login, or to ensure that the session validator gets to
    098        // mandate its page selection policy for non-logged in users
    099        // after the logout has taken place.
    100        String actionName = data.getAction();
    101        if (data.hasAction() &&
    102            actionName.equalsIgnoreCase(actionLogin) ||
    103            actionName.equalsIgnoreCase(actionLogout))
    104        {
    105            // If a User is logging in, we should refresh the
    106            // session here.  Invalidating session and starting a
    107            // new session would seem to be a good method, but I
    108            // (JDM) could not get this to work well (it always
    109            // required the user to login twice).  Maybe related
    110            // to JServ?  If we do not clear out the session, it
    111            // is possible a new User may accidently (if they
    112            // login incorrectly) continue on with information
    113            // associated with the previous User.  Currently the
    114            // only keys stored in the session are "turbine.user"
    115            // and "turbine.acl".
    116            if (actionName.equalsIgnoreCase(actionLogin))
    117            {
    118                @SuppressWarnings("unchecked")
    119                Enumeration<String> names = data.getSession().getAttributeNames();
    120                if (names != null)
    121                {
    122                    // copy keys into a new list, so we can clear the session
    123                    // and not get ConcurrentModificationException
    124                    List<String> nameList = new ArrayList<String>();
    125                    while (names.hasMoreElements())
    126                    {
    127                        nameList.add(names.nextElement());
    128                    }
    129
    130                    HttpSession session = data.getSession();
    131                    for (String name : nameList)
    132                    {
    133                        try
    134                        {
    135                            session.removeAttribute(name);
    136                        }
    137                        catch (IllegalStateException invalidatedSession)
    138                        {
    139                            break;
    140                        }
    141                    }
    142                }
    143            }
    144
    145            actionLoader.exec(pipelineData, data.getAction());
    146            cleanupTemplateContext(data);
    147            data.setAction(null);
    148        }
    149    }
    150
    151    /**
    152     * cleans the Velocity Context if available.
    153     *
    154     * @param data A RunData Object
    155     */
    156    private void cleanupTemplateContext(RunData data)
    157    {
    158        // This is Velocity specific and shouldn't be done here.
    159        // But this is a band aid until we get real listeners
    160        // here.
    161        TemplateInfo ti = data.getTemplateInfo();
    162        if (ti != null)
    163        {
    164            ti.removeTemp(VelocityService.CONTEXT);
    165        }
    166    }
    167}