1/*2 * Licensed to the Apache Software Foundation (ASF) under one or more3 * contributor license agreements. See the NOTICE file distributed with4 * this work for additional information regarding copyright ownership.5 * The ASF licenses this file to You under the Apache License, Version 2.06 * (the "License"); you may not use this file except in compliance with7 * the License. You may obtain a copy of the License at8 * 9 * http://www.apache.org/licenses/LICENSE-2.010 * 11 * Unless required by applicable law or agreed to in writing, software12 * 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 and15 * limitations under the License.16 */17packageorg.apache.jetspeed.container.session;
1819import java.util.Arrays;
20import java.util.Collection;
21import java.util.Collections;
22import java.util.HashMap;
23import java.util.Iterator;
24import java.util.Map;
2526import javax.servlet.http.HttpSession;
2728import org.apache.commons.logging.Log;
29import org.apache.commons.logging.LogFactory;
3031/***32 * PortalSessionsManagerImpl33 *34 * @author <a href="mailto:ate@douma.nu">Ate Douma</a>35 * @version $Id: $36 */37publicclassPortalSessionsManagerImpl implements PortalSessionsManager
38 {
3940privatestatic Log log = LogFactory.getLog(PortalSessionsManagerImpl.class);
4142privatestaticfinalclass PortalSessionRegistry
43 {
44long portalSessionKey;
45 PortalSessionMonitor psm;
46 Map sessionMonitors;
4748 PortalSessionRegistry()
49 {
50 sessionMonitors = Collections.synchronizedMap(new HashMap());
51 }
52 }
5354privatelong portalSessionKeySequence;
55private Map portalSessionsRegistry;
56privateboolean forceInvalidate;
5758publicPortalSessionsManagerImpl()
59 {
60this(true);
61 }
6263publicPortalSessionsManagerImpl(boolean forceInvalidate)
64 {
65 portalSessionKeySequence = System.currentTimeMillis();
66 portalSessionsRegistry = Collections.synchronizedMap(new HashMap());
67this.forceInvalidate = forceInvalidate;
68 }
6970/* (non-Javadoc)71 * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionCreated(javax.servlet.http.HttpSession)72 */73publicvoid portalSessionCreated(HttpSession portalSession)
74 {
75 PortalSessionMonitor psm = null;
7677synchronized (this)
78 {
79 psm = newPortalSessionMonitorImpl(++portalSessionKeySequence, forceInvalidate);
80 }
8182 portalSession.setAttribute(PortalSessionMonitor.SESSION_KEY, psm);
83// register it as if activated84 portalSessionDidActivate(psm);
85 }
8687/* (non-Javadoc)88 * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionWillPassivate(org.apache.jetspeed.container.session.PortalSessionMonitor)89 */90publicvoid portalSessionWillPassivate(PortalSessionMonitor psm)
91 {
92 portalSessionsRegistry.remove(psm.getSessionId());
93 }
9495/* (non-Javadoc)96 * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionDidActivate(org.apache.jetspeed.container.session.PortalSessionMonitor)97 */98publicvoid portalSessionDidActivate(PortalSessionMonitor restoredPsm)
99 {
100 PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(restoredPsm.getSessionId());
101if ( psr != null && psr.portalSessionKey != -1 && psr.portalSessionKey != restoredPsm.getSessionKey() )
102 {
103// looks like Client didn't join the previous portal session while the sessionId is reused (cookies disabled?)104// destroy the "old" portal Session and any (probably also not-joined) registered paSessions105 portalSessionDestroyed(psr.psm);
106 psr = null;
107 }
108if ( psr == null )
109 {
110 psr = new PortalSessionRegistry();
111 portalSessionsRegistry.put(restoredPsm.getSessionId(), psr);
112 }
113// save the restored instance114 psr.psm = restoredPsm;
115 psr.portalSessionKey = restoredPsm.getSessionKey();
116// validate registered paSessions are in sync117// we iterate with shallow copy of paSessions to avoid conflicts with concurrent updates of paSessions118 Iterator iter = valuesShallowCopy(psr.sessionMonitors.values()).iterator();
119 PortletApplicationSessionMonitor pasm;
120while (iter.hasNext())
121 {
122 pasm = (PortletApplicationSessionMonitor)iter.next();
123if ( pasm.getPortalSessionKey() != psr.portalSessionKey )
124 {
125 pasm.invalidateSession();
126// remove from original map !127 psr.sessionMonitors.remove(pasm.getContextPath());
128 }
129 }
130 }
131132/* (non-Javadoc)133 * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionDestroyed(org.apache.jetspeed.container.session.PortalSessionMonitor)134 */135publicvoid portalSessionDestroyed(PortalSessionMonitor psm)
136 {
137 PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.remove(psm.getSessionId());
138if ( psr != null )
139 {
140// we iterate with shallow copy of paSessions to avoid conflicts with concurrent updates of paSessions141 Iterator iter = valuesShallowCopy(psr.sessionMonitors.values()).iterator();
142while (iter.hasNext())
143 {
144 ((PortletApplicationSessionMonitor) iter.next()).invalidateSession();
145 }
146147try148 {
149// To make sure its gone.150// You better not remove the psm from the portal session yourself ;)151 psm.invalidateSession();
152 }
153catch (IllegalStateException ise)
154 {
155// pSession already invalid, ignore156 }
157 }
158 }
159160/* (non-Javadoc)161 * @see org.apache.jetspeed.container.session.PortalSessionsManager#checkMonitorSession(java.lang.String, javax.servlet.http.HttpSession, javax.servlet.http.HttpSession)162 */163publicvoid checkMonitorSession(String contextPath, HttpSession portalSession, HttpSession paSession)
164 {
165if ( portalSession != null && paSession != null )
166 {
167if (portalSession == paSession)
168 {
169// On WebSphere 6.1.0.11, strange symptoms like this occur...170 log.warn("servlet context name of paSession(" + paSession.getId() + "): " + paSession.getServletContext().getServletContextName());
171return;
172 }
173174 PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(portalSession.getId());
175if (psr == null)
176 {
177// yet unexplained condition: the HttpSessionListener on the portal application *should* have registered the session!!!178// Alas, it has been reported to happen...179// Now trying to do some recovering here180 PortalSessionMonitor psm = (PortalSessionMonitor)portalSession.getAttribute(PortalSessionMonitor.SESSION_KEY);
181// the psm better be null here, otherwise something really is corrupt or not playing by the listeners contracts182if ( psm == null )
183 {
184 portalSessionCreated(portalSession);
185 }
186else187 {
188// Now we have discovered a really strange situation here189// Only explanation I can see is that a passivation of the portalSession occurred, 190// but that the activation again didn't trigger the sessionDidActivate event handler???191// Lets just try to accomodate this situation for now:192 portalSessionDidActivate(psm);
193 }
194// now retrieve the just created psr again195 psr = (PortalSessionRegistry)portalSessionsRegistry.get(portalSession.getId());
196 }
197 PortletApplicationSessionMonitor pasm = (PortletApplicationSessionMonitor)psr.sessionMonitors.get(contextPath);
198if ( pasm != null )
199 {
200try201 {
202if ( paSession.getAttribute(PortletApplicationSessionMonitor.SESSION_KEY) == null )
203 {
204// looks like Client didn't join the previous pa session205// destroy the "old" paSession206 pasm.invalidateSession();
207 pasm = null;
208// no need to remove the "old" pasm from the sessionMonitors as it will be replaced right below209 }
210 }
211catch (IllegalStateException ise)
212 {
213// paSession already invalid, ignore214 }
215 }
216if ( pasm == null )
217 {
218 pasm = new PortletApplicationSessionMonitorImpl(contextPath,portalSession.getId(),psr.portalSessionKey, forceInvalidate);
219try220 {
221 paSession.setAttribute(PortletApplicationSessionMonitor.SESSION_KEY, pasm);
222 psr.sessionMonitors.put(contextPath, pasm);
223 }
224catch (IllegalStateException ise)
225 {
226// paSession already invalid, ignore227 }
228 }
229 }
230 }
231232/* (non-Javadoc)233 * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionWillPassivate(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)234 */235publicvoid sessionWillPassivate(PortletApplicationSessionMonitor pasm)
236 {
237 PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(pasm.getPortalSessionId());
238if (psr != null )
239 {
240 psr.sessionMonitors.remove(pasm.getContextPath());
241 }
242 }
243244/* (non-Javadoc)245 * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionDidActivate(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)246 */247publicvoid sessionDidActivate(PortletApplicationSessionMonitor restoredPasm)
248 {
249 PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(restoredPasm.getPortalSessionId());
250if ( psr == null )
251 {
252// looks like the portalSession was passivated or the paSession was replicated to another JVM while its related portalSession wasn't (yet)253// so, we're gonna anticipate future activation of the portalSession:254// create a temporary psr with an "empty" psm for now (portalSessionKey == -1)255// once the portalSession is replicated/Activated, it will validate registered paSessions having the correct portalSessionKey256 psr = new PortalSessionRegistry();
257 psr.psm = newPortalSessionMonitorImpl(-1);
258 portalSessionsRegistry.put(restoredPasm.getPortalSessionId(), psr);
259 }
260261// save the restored instance262 restoredPasm.getSession().setAttribute(PortletApplicationSessionMonitor.SESSION_KEY, restoredPasm);
263 psr.sessionMonitors.put(restoredPasm.getContextPath(), restoredPasm);
264 }
265266/* (non-Javadoc)267 * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionDestroyed(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)268 */269publicvoid sessionDestroyed(PortletApplicationSessionMonitor pasm)
270 {
271 PortalSessionRegistry psr = (PortalSessionRegistry)portalSessionsRegistry.get(pasm.getPortalSessionId());
272if ( psr != null )
273 {
274 psr.sessionMonitors.remove(pasm.getContextPath());
275276try277 {
278// To make sure its gone.279// You better not remove the pasm from the session yourself ;)280 pasm.invalidateSession();
281 }
282catch (IllegalStateException ise)
283 {
284// paSession already invalid, ignore285 }
286 }
287 }
288289/* (non-Javadoc)290 * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionCount()291 */292publicint sessionCount() {
293294return portalSessionsRegistry.size();
295 }
296297/***298 * Returns a shallow copy of the given Collection.299 * @param inValues300 * @return shallow copy301 */302private Collection valuesShallowCopy(Collection inValues) {
303return Arrays.asList(inValues.toArray());
304 }
305 }