View Javadoc
1   package org.apache.turbine.pipeline;
2   
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21   */
22  
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Enumeration;
27  import java.util.List;
28  
29  import javax.servlet.http.HttpSession;
30  
31  import org.apache.turbine.TurbineConstants;
32  import org.apache.turbine.annotation.TurbineConfiguration;
33  import org.apache.turbine.annotation.TurbineLoader;
34  import org.apache.turbine.modules.Action;
35  import org.apache.turbine.modules.ActionLoader;
36  import org.apache.turbine.services.velocity.VelocityService;
37  import org.apache.turbine.util.RunData;
38  import org.apache.turbine.util.TurbineException;
39  import org.apache.turbine.util.template.TemplateInfo;
40  
41  /**
42   * Handles the Login and Logout actions in the request process
43   * cycle.
44   *
45   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
46   * @author <a href="mailto:dlr@apache.org">Daniel Rall</a>
47   * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
48   * @version $Id$
49   */
50  public class DefaultLoginValve
51      implements Valve
52  {
53      /** Injected loader instance */
54      @TurbineLoader( Action.class )
55      private ActionLoader actionLoader;
56  
57      @TurbineConfiguration( TurbineConstants.ACTION_LOGIN_KEY )
58      private String actionLogin;
59  
60      @TurbineConfiguration( TurbineConstants.ACTION_LOGOUT_KEY )
61      private String actionLogout;
62  
63      /**
64       * @see org.apache.turbine.pipeline.Valve#invoke(PipelineData, ValveContext)
65       */
66      @Override
67      public void invoke(PipelineData pipelineData, ValveContext context)
68          throws IOException, TurbineException
69      {
70          try
71          {
72              process(pipelineData);
73          }
74          catch (Exception e)
75          {
76              throw new TurbineException(e);
77          }
78  
79          // Pass control to the next Valve in the Pipeline
80          context.invokeNext(pipelineData);
81      }
82  
83      /**
84       * Handles user sessions, parsing of the action from the query
85       * string, and access control.
86       *
87       * @param pipelineData The run-time data.
88       *
89       * @throws Exception if executing the action fails
90       */
91      protected void process(PipelineData pipelineData)
92          throws Exception
93      {
94          RunData data = pipelineData.getRunData();
95          // Special case for login and logout, this must happen before the
96          // session validator is executed in order either to allow a user to
97          // even login, or to ensure that the session validator gets to
98          // mandate its page selection policy for non-logged in users
99          // 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                 Enumeration<String> names = data.getSession().getAttributeNames();
119                 if (names != null)
120                 {
121                     // copy keys into a new list, so we can clear the session
122                     // and not get ConcurrentModificationException
123                     List<String> nameList = new ArrayList<>();
124                     while (names.hasMoreElements())
125                     {
126                         nameList.add(names.nextElement());
127                     }
128 
129                     HttpSession session = data.getSession();
130                     for (String name : nameList)
131                     {
132                         try
133                         {
134                             session.removeAttribute(name);
135                         }
136                         catch (IllegalStateException invalidatedSession)
137                         {
138                             break;
139                         }
140                     }
141                 }
142             }
143 
144             actionLoader.exec(pipelineData, data.getAction());
145             cleanupTemplateContext(data);
146             data.setAction(null);
147         }
148     }
149 
150     /**
151      * cleans the Velocity Context if available.
152      *
153      * @param data A RunData Object
154      */
155     private void cleanupTemplateContext(RunData data)
156     {
157         // This is Velocity specific and shouldn't be done here.
158         // But this is a band aid until we get real listeners
159         // here.
160         TemplateInfo ti = data.getTemplateInfo();
161         if (ti != null)
162         {
163             ti.removeTemp(VelocityService.CONTEXT);
164         }
165     }
166 }