View Javadoc

1   // ========================================================================
2   // Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // Licensed under the Apache License, Version 2.0 (the "License");
5   // you may not use this file except in compliance with the License.
6   // You may obtain a copy of the License at
7   // http://www.apache.org/licenses/LICENSE-2.0
8   // Unless required by applicable law or agreed to in writing, software
9   // distributed under the License is distributed on an "AS IS" BASIS,
10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  // See the License for the specific language governing permissions and
12  // limitations under the License.
13  // ========================================================================
14  
15  package org.mortbay.terracotta.servlet;
16  
17  import java.io.IOException;
18  
19  import javax.servlet.ServletException;
20  import javax.servlet.http.Cookie;
21  import javax.servlet.http.HttpServletRequest;
22  import javax.servlet.http.HttpServletResponse;
23  import javax.servlet.http.HttpSession;
24  
25  import org.mortbay.jetty.HttpConnection;
26  import org.mortbay.jetty.Request;
27  import org.mortbay.jetty.RetryRequest;
28  import org.mortbay.jetty.SessionManager;
29  import org.mortbay.jetty.servlet.SessionHandler;
30  import org.mortbay.log.Log;
31  
32  /**
33   * A specific subclass of {@link SessionHandler} that sets a contract between
34   * this class and {@link TerracottaSessionManager}.
35   * The contract requires that a Terracotta named lock will be held for the duration
36   * of the request, where the lock name depends on the session id.
37   * To achieve this, we call {@link TerracottaSessionManager#enter(Request)} and
38   * {@link TerracottaSessionManager#exit(Request)}, in order to be able to obtain
39   * and release the Terracotta lock.
40   * See the {@link TerracottaSessionManager} javadocs for implementation notes.
41   *
42   * @version $Revision: 1308 $ $Date: 2008-11-07 21:50:17 +1100 (Fri, 07 Nov 2008) $
43   */
44  public class TerracottaSessionHandler extends SessionHandler
45  {
46      public TerracottaSessionHandler()
47      {
48      }
49  
50      public TerracottaSessionHandler(SessionManager manager)
51      {
52          super(manager);
53      }
54  
55      @Override
56      public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException
57      {
58          setRequestedId(request, dispatch);
59  
60          Request currentRequest = (request instanceof Request) ? (Request)request : HttpConnection.getCurrentConnection().getRequest();
61  
62          SessionManager requestSessionManager = currentRequest.getSessionManager();
63          HttpSession requestSession = currentRequest.getSession(false);
64  
65          TerracottaSessionManager sessionManager = (TerracottaSessionManager)getSessionManager();
66          Log.debug("SessionManager = {}", sessionManager);
67  
68          // Is it a cross context dispatch or a direct hit to this context ?
69          if (sessionManager != requestSessionManager)
70          {
71              // Setup the request for this context
72              currentRequest.setSessionManager(sessionManager);
73              currentRequest.setSession(null);
74          }
75  
76          // Tell the session manager that the request is entering
77          if (sessionManager != null) sessionManager.enter(currentRequest);
78          try
79          {
80              HttpSession currentSession = null;
81              if (sessionManager != null)
82              {
83                  currentSession = currentRequest.getSession(false);
84                  if (currentSession != null)
85                  {
86                      if (currentSession != requestSession)
87                      {
88                          // Access the session only if we did not already
89                          Cookie cookie = sessionManager.access(currentSession, request.isSecure());
90                          if (cookie != null)
91                          {
92                              // Handle changed session id or cookie max-age refresh
93                              response.addCookie(cookie);
94                          }
95                      }
96                      else
97                      {
98                          // Handle resume of the request
99                          currentSession = currentRequest.recoverNewSession(sessionManager);
100                         if (currentSession != null) currentRequest.setSession(currentSession);
101                     }
102                 }
103             }
104             Log.debug("Session = {}", currentSession);
105 
106             getHandler().handle(target, request, response, dispatch);
107         }
108         catch (RetryRequest x)
109         {
110             // User may have invalidated the session, must get it again
111             HttpSession currentSession = currentRequest.getSession(false);
112             if (currentSession != null && currentSession.isNew())
113                 currentRequest.saveNewSession(sessionManager, currentSession);
114 
115             throw x;
116         }
117         finally
118         {
119             if (sessionManager != null)
120             {
121                 // User may have invalidated the session, must get it again
122                 HttpSession currentSession = currentRequest.getSession(false);
123                 if (currentSession != null) sessionManager.complete(currentSession);
124 
125                 sessionManager.exit(currentRequest);
126             }
127 
128             // Restore cross context dispatch
129             if (sessionManager != requestSessionManager)
130             {
131                 currentRequest.setSessionManager(requestSessionManager);
132                 currentRequest.setSession(requestSession);
133             }
134         }
135     }
136 }