View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.server.session;
20  
21  import java.lang.ref.WeakReference;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.Iterator;
28  import java.util.Map;
29  import java.util.Random;
30  import java.util.Set;
31  
32  import javax.servlet.http.HttpServletRequest;
33  import javax.servlet.http.HttpSession;
34  
35  import org.eclipse.jetty.server.SessionIdManager;
36  
37  /* ------------------------------------------------------------ */
38  /**
39   * HashSessionIdManager. An in-memory implementation of the session ID manager.
40   */
41  public class HashSessionIdManager extends AbstractSessionIdManager
42  {
43      private final Map<String, Set<WeakReference<HttpSession>>> _sessions = new HashMap<String, Set<WeakReference<HttpSession>>>();
44  
45      /* ------------------------------------------------------------ */
46      public HashSessionIdManager()
47      {
48      }
49  
50      /* ------------------------------------------------------------ */
51      public HashSessionIdManager(Random random)
52      {
53          super(random);
54      }
55  
56      /* ------------------------------------------------------------ */
57      /**
58       * @return Collection of String session IDs
59       */
60      public Collection<String> getSessions()
61      {
62          return Collections.unmodifiableCollection(_sessions.keySet());
63      }
64  
65      /* ------------------------------------------------------------ */
66      /**
67       * @return Collection of Sessions for the passed session ID
68       */
69      public Collection<HttpSession> getSession(String id)
70      {
71          ArrayList<HttpSession> sessions = new ArrayList<HttpSession>();
72          Set<WeakReference<HttpSession>> refs =_sessions.get(id);
73          if (refs!=null)
74          {
75              for (WeakReference<HttpSession> ref: refs)
76              {
77                  HttpSession session = ref.get();
78                  if (session!=null)
79                      sessions.add(session);
80              }
81          }
82          return sessions;
83      }
84      /* ------------------------------------------------------------ */
85      /** Get the session ID with any worker ID.
86       *
87       * @param clusterId
88       * @param request
89       * @return sessionId plus any worker ID.
90       */
91      public String getNodeId(String clusterId,HttpServletRequest request)
92      {
93          // used in Ajp13Parser
94          String worker=request==null?null:(String)request.getAttribute("org.eclipse.jetty.ajp.JVMRoute");
95          if (worker!=null)
96              return clusterId+'.'+worker;
97  
98          if (_workerName!=null)
99              return clusterId+'.'+_workerName;
100 
101         return clusterId;
102     }
103 
104     /* ------------------------------------------------------------ */
105     /** Get the session ID without any worker ID.
106      *
107      * @param nodeId the node id
108      * @return sessionId without any worker ID.
109      */
110     public String getClusterId(String nodeId)
111     {
112         int dot=nodeId.lastIndexOf('.');
113         return (dot>0)?nodeId.substring(0,dot):nodeId;
114     }
115 
116     /* ------------------------------------------------------------ */
117     @Override
118     protected void doStart() throws Exception
119     {
120         super.doStart();
121     }
122 
123     /* ------------------------------------------------------------ */
124     @Override
125     protected void doStop() throws Exception
126     {
127         _sessions.clear();
128         super.doStop();
129     }
130 
131     /* ------------------------------------------------------------ */
132     /**
133      * @see SessionIdManager#idInUse(String)
134      */
135     public boolean idInUse(String id)
136     {
137         synchronized (this)
138         {
139             return _sessions.containsKey(id);
140         }
141     }
142 
143     /* ------------------------------------------------------------ */
144     /**
145      * @see SessionIdManager#addSession(HttpSession)
146      */
147     public void addSession(HttpSession session)
148     {
149         String id = getClusterId(session.getId());
150         WeakReference<HttpSession> ref = new WeakReference<HttpSession>(session);
151 
152         synchronized (this)
153         {
154             Set<WeakReference<HttpSession>> sessions = _sessions.get(id);
155             if (sessions==null)
156             {
157                 sessions=new HashSet<WeakReference<HttpSession>>();
158                 _sessions.put(id,sessions);
159             }
160             sessions.add(ref);
161         }
162     }
163 
164     /* ------------------------------------------------------------ */
165     /**
166      * @see SessionIdManager#removeSession(HttpSession)
167      */
168     public void removeSession(HttpSession session)
169     {
170         String id = getClusterId(session.getId());
171 
172         synchronized (this)
173         {
174             Collection<WeakReference<HttpSession>> sessions = _sessions.get(id);
175             if (sessions!=null)
176             {
177                 for (Iterator<WeakReference<HttpSession>> iter = sessions.iterator(); iter.hasNext();)
178                 {
179                     WeakReference<HttpSession> ref = iter.next();
180                     HttpSession s=ref.get();
181                     if (s==null)
182                     {
183                         iter.remove();
184                         continue;
185                     }
186                     if (s==session)
187                     {
188                         iter.remove();
189                         break;
190                     }
191                 }
192                 if (sessions.isEmpty())
193                     _sessions.remove(id);
194             }
195         }
196     }
197 
198     /* ------------------------------------------------------------ */
199     /**
200      * @see SessionIdManager#invalidateAll(String)
201      */
202     public void invalidateAll(String id)
203     {
204         Collection<WeakReference<HttpSession>> sessions;
205         synchronized (this)
206         {
207             sessions = _sessions.remove(id);
208         }
209 
210         if (sessions!=null)
211         {
212             for (WeakReference<HttpSession> ref: sessions)
213             {
214                 AbstractSession session=(AbstractSession)ref.get();
215                 if (session!=null && session.isValid())
216                     session.invalidate();
217             }
218             sessions.clear();
219         }
220     }
221     
222     
223     /* ------------------------------------------------------------ */
224     public void renewSessionId (String oldClusterId, String oldNodeId, HttpServletRequest request)
225     {
226         //generate a new id
227         String newClusterId = newSessionId(request.hashCode());
228 
229 
230         synchronized (this)
231         {
232             Set<WeakReference<HttpSession>> sessions = _sessions.remove(oldClusterId); //get the list of sessions with same id from other contexts
233             if (sessions!=null)
234             {
235                 for (Iterator<WeakReference<HttpSession>> iter = sessions.iterator(); iter.hasNext();)
236                 {
237                     WeakReference<HttpSession> ref = iter.next();
238                     HttpSession s = ref.get();
239                     if (s == null)
240                     {
241                         continue;
242                     }
243                     else
244                     {
245                         if (s instanceof AbstractSession)
246                         {
247                             AbstractSession abstractSession = (AbstractSession)s;
248                             abstractSession.getSessionManager().renewSessionId(oldClusterId, oldNodeId, newClusterId, getNodeId(newClusterId, request));
249                         }
250                     }
251                 }
252                 _sessions.put(newClusterId, sessions);
253             }
254         }
255     }
256 
257 }