View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.container.session;
18  
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.Iterator;
22  import java.util.Map;
23  
24  import javax.servlet.http.HttpSession;
25  
26  /***
27   * PortalSessionsManagerImpl
28   *
29   * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
30   * @version $Id: $
31   */
32  public class PortalSessionsManagerImpl implements PortalSessionsManager
33  {
34      private static final class PortalSessionRegistry
35      {
36          long portalSessionKey;
37          PortalSessionMonitor psm;
38          Map sessionMonitors;
39          
40          PortalSessionRegistry()
41          {
42              sessionMonitors = Collections.synchronizedMap(new HashMap());
43          }
44      }
45      
46      private long portalSessionKeySequence;
47      private Map portalSessionsRegistry;
48      private boolean forceInvalidate;
49      
50      public PortalSessionsManagerImpl()
51      {
52          this(true);        
53      }
54      
55      public PortalSessionsManagerImpl(boolean forceInvalidate)
56      {
57          portalSessionKeySequence = System.currentTimeMillis();
58          portalSessionsRegistry = Collections.synchronizedMap(new HashMap());
59          this.forceInvalidate = forceInvalidate;
60      }
61      
62      /* (non-Javadoc)
63       * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionCreated(javax.servlet.http.HttpSession)
64       */
65      public synchronized void portalSessionCreated(HttpSession portalSession)
66      {
67          PortalSessionMonitor psm = new PortalSessionMonitorImpl(++portalSessionKeySequence, forceInvalidate);
68          portalSession.setAttribute(PortalSessionMonitor.SESSION_KEY, psm);
69          // register it as if activated
70          portalSessionDidActivate(psm);
71      }
72      
73      /* (non-Javadoc)
74       * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionWillPassivate(org.apache.jetspeed.container.session.PortalSessionMonitor)
75       */
76      public synchronized void portalSessionWillPassivate(PortalSessionMonitor psm)
77      {
78          portalSessionsRegistry.remove(psm.getSessionId());
79      }
80  
81      /* (non-Javadoc)
82       * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionDidActivate(org.apache.jetspeed.container.session.PortalSessionMonitor)
83       */
84      public synchronized void portalSessionDidActivate(PortalSessionMonitor restoredPsm)
85      {
86          PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(restoredPsm.getSessionId());
87          if ( psr != null && psr.portalSessionKey != -1 && psr.portalSessionKey != restoredPsm.getSessionKey() )
88          {
89              // looks like Client didn't join the previous portal session while the sessionId is reused (cookies disabled?)
90              // destroy the "old" portal Session and any (probably also not-joined) registered paSessions
91              portalSessionDestroyed(psr.psm);
92              psr = null;
93          }
94          if ( psr == null )
95          {
96              psr = new PortalSessionRegistry();
97              portalSessionsRegistry.put(restoredPsm.getSessionId(), psr);
98          }
99          // save the restored instance
100         psr.psm = restoredPsm;
101         psr.portalSessionKey = restoredPsm.getSessionKey();
102         // validate registered paSessions are in sync
103         Iterator iter = psr.sessionMonitors.values().iterator();
104         PortletApplicationSessionMonitor pasm;
105         while (iter.hasNext())
106         {
107             pasm = (PortletApplicationSessionMonitor)iter.next();
108             if ( pasm.getPortalSessionKey() != psr.portalSessionKey )
109             {
110                 pasm.invalidateSession();
111                 iter.remove();
112             }
113         }
114     }
115 
116     /* (non-Javadoc)
117      * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionDestroyed(org.apache.jetspeed.container.session.PortalSessionMonitor)
118      */
119     public synchronized void portalSessionDestroyed(PortalSessionMonitor psm)
120     {
121         PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.remove(psm.getSessionId());
122         if ( psr != null )
123         {
124             Iterator iter = psr.sessionMonitors.values().iterator();
125             while (iter.hasNext())
126             {
127                 ((PortletApplicationSessionMonitor)iter.next()).invalidateSession();
128             }
129             // To make sure its gone.
130             // You better not remove the psm from the portal session yourself ;)
131             psm.invalidateSession();
132         }
133     }
134 
135     /* (non-Javadoc)
136      * @see org.apache.jetspeed.container.session.PortalSessionsManager#checkMonitorSession(java.lang.String, javax.servlet.http.HttpSession, javax.servlet.http.HttpSession)
137      */
138     public synchronized void checkMonitorSession(String contextPath, HttpSession portalSession, HttpSession paSession)
139     {
140         if ( portalSession != null && paSession != null )
141         {
142             PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(portalSession.getId());
143             if (psr == null)
144             {
145                 // yet unexplained condition: the HttpSessionListener on the portal application *should* have registered the session!!!
146                 // Alas, it has been reported to happen...
147                 // Now trying to do some recovering here
148                 PortalSessionMonitor psm = (PortalSessionMonitor)portalSession.getAttribute(PortalSessionMonitor.SESSION_KEY);
149                 // the psm better be null here, otherwise something really is corrupt or not playing by the listeners contracts
150                 if ( psm == null )
151                 {
152                     portalSessionCreated(portalSession);
153                 }
154                 else
155                 {
156                     // Now we have discovered a really strange situation here
157                     // Only explanation I can see is that a passivation of the portalSession occurred, 
158                     // but that the activation again didn't trigger the sessionDidActivate event handler???
159                    // Lets just try to accomodate this situation for now:
160                     portalSessionDidActivate(psm);
161                 }
162                 // now retrieve the just created psr again
163                 psr = (PortalSessionRegistry)portalSessionsRegistry.get(portalSession.getId());
164             }
165             PortletApplicationSessionMonitor pasm = (PortletApplicationSessionMonitor)psr.sessionMonitors.get(contextPath);
166             if ( pasm != null )
167             {
168                 try
169                 {
170                     if ( paSession.getAttribute(PortletApplicationSessionMonitor.SESSION_KEY) == null )
171                     {
172                         // looks like Client didn't join the previous pa session
173                         // destroy the "old" paSession
174                         pasm.invalidateSession();                    
175                         pasm = null;
176                         // no need to remove the "old" pasm from the sessionMonitors as it will be replaced right below
177                     }
178                 }
179                 catch (IllegalStateException ise)
180                 {
181                     // paSession already invalid, ignore
182                 }
183             }
184             if ( pasm == null )
185             {
186                 pasm = new PortletApplicationSessionMonitorImpl(contextPath,portalSession.getId(),psr.portalSessionKey, forceInvalidate);
187                 try
188                 {
189                     paSession.setAttribute(PortletApplicationSessionMonitor.SESSION_KEY, pasm);
190                     psr.sessionMonitors.put(contextPath, pasm);
191                 }
192                 catch (IllegalStateException ise)
193                 {
194                     // paSession already invalid, ignore
195                 }
196             }
197         }
198     }
199     
200     /* (non-Javadoc)
201      * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionWillPassivate(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)
202      */
203     public void sessionWillPassivate(PortletApplicationSessionMonitor pasm)
204     {
205         PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(pasm.getPortalSessionId());
206         if (psr != null )
207         {
208             psr.sessionMonitors.remove(pasm.getContextPath());
209         }
210     }
211 
212     /* (non-Javadoc)
213      * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionDidActivate(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)
214      */
215     public synchronized void sessionDidActivate(PortletApplicationSessionMonitor restoredPasm)
216     {
217         PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(restoredPasm.getPortalSessionId());
218         if ( psr == null )
219         {
220             // looks like the portalSession was passivated or the paSession was replicated to another JVM while its related portalSession wasn't (yet)
221             // so, we're gonna anticipate future activation of the portalSession:
222             // create a temporary psr with an "empty" psm for now (portalSessionKey == -1)
223             // once the portalSession is replicated/Activated, it will validate registered paSessions having the correct portalSessionKey
224             psr = new PortalSessionRegistry();
225             psr.psm = new PortalSessionMonitorImpl(-1);
226             portalSessionsRegistry.put(restoredPasm.getPortalSessionId(), psr);
227         }
228         // save the restored instance
229         psr.sessionMonitors.put(restoredPasm.getContextPath(), restoredPasm);
230     }
231 
232     /* (non-Javadoc)
233      * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionDestroyed(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)
234      */
235     public synchronized void sessionDestroyed(PortletApplicationSessionMonitor pasm)
236     {
237         PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(pasm.getPortalSessionId());
238         if ( psr != null )
239         {
240             psr.sessionMonitors.remove(pasm.getContextPath());
241             // To make sure its gone.
242             // You better not remove the pasm from the session yourself ;)
243             pasm.invalidateSession();
244         }
245     }
246 
247 	/* (non-Javadoc)
248 	 * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionCount()
249 	 */
250 	public int sessionCount() {
251 		
252 		return portalSessionsRegistry.size();
253 	}
254 }