001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.container.session;
018:
019: import java.util.Arrays;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.Map;
025:
026: import javax.servlet.http.HttpSession;
027:
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030:
031: /**
032: * PortalSessionsManagerImpl
033: *
034: * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
035: * @version $Id: $
036: */
037: public class PortalSessionsManagerImpl implements PortalSessionsManager {
038:
039: private static Log log = LogFactory
040: .getLog(PortalSessionsManagerImpl.class);
041:
042: private static final class PortalSessionRegistry {
043: long portalSessionKey;
044: PortalSessionMonitor psm;
045: Map sessionMonitors;
046:
047: PortalSessionRegistry() {
048: sessionMonitors = Collections
049: .synchronizedMap(new HashMap());
050: }
051: }
052:
053: private long portalSessionKeySequence;
054: private Map portalSessionsRegistry;
055: private boolean forceInvalidate;
056:
057: public PortalSessionsManagerImpl() {
058: this (true);
059: }
060:
061: public PortalSessionsManagerImpl(boolean forceInvalidate) {
062: portalSessionKeySequence = System.currentTimeMillis();
063: portalSessionsRegistry = Collections
064: .synchronizedMap(new HashMap());
065: this .forceInvalidate = forceInvalidate;
066: }
067:
068: /* (non-Javadoc)
069: * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionCreated(javax.servlet.http.HttpSession)
070: */
071: public void portalSessionCreated(HttpSession portalSession) {
072: PortalSessionMonitor psm = null;
073:
074: synchronized (this ) {
075: psm = new PortalSessionMonitorImpl(
076: ++portalSessionKeySequence, forceInvalidate);
077: }
078:
079: portalSession.setAttribute(PortalSessionMonitor.SESSION_KEY,
080: psm);
081: // register it as if activated
082: portalSessionDidActivate(psm);
083: }
084:
085: /* (non-Javadoc)
086: * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionWillPassivate(org.apache.jetspeed.container.session.PortalSessionMonitor)
087: */
088: public void portalSessionWillPassivate(PortalSessionMonitor psm) {
089: portalSessionsRegistry.remove(psm.getSessionId());
090: }
091:
092: /* (non-Javadoc)
093: * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionDidActivate(org.apache.jetspeed.container.session.PortalSessionMonitor)
094: */
095: public void portalSessionDidActivate(
096: PortalSessionMonitor restoredPsm) {
097: PortalSessionRegistry psr = (PortalSessionRegistry) portalSessionsRegistry
098: .get(restoredPsm.getSessionId());
099: if (psr != null && psr.portalSessionKey != -1
100: && psr.portalSessionKey != restoredPsm.getSessionKey()) {
101: // looks like Client didn't join the previous portal session while the sessionId is reused (cookies disabled?)
102: // destroy the "old" portal Session and any (probably also not-joined) registered paSessions
103: portalSessionDestroyed(psr.psm);
104: psr = null;
105: }
106: if (psr == null) {
107: psr = new PortalSessionRegistry();
108: portalSessionsRegistry.put(restoredPsm.getSessionId(), psr);
109: }
110: // save the restored instance
111: psr.psm = restoredPsm;
112: psr.portalSessionKey = restoredPsm.getSessionKey();
113: // validate registered paSessions are in sync
114: // we iterate with shallow copy of paSessions to avoid conflicts with concurrent updates of paSessions
115: Iterator iter = valuesShallowCopy(psr.sessionMonitors.values())
116: .iterator();
117: PortletApplicationSessionMonitor pasm;
118: while (iter.hasNext()) {
119: pasm = (PortletApplicationSessionMonitor) iter.next();
120: if (pasm.getPortalSessionKey() != psr.portalSessionKey) {
121: pasm.invalidateSession();
122: // remove from original map !
123: psr.sessionMonitors.remove(pasm.getContextPath());
124: }
125: }
126: }
127:
128: /* (non-Javadoc)
129: * @see org.apache.jetspeed.container.session.PortalSessionsManager#portalSessionDestroyed(org.apache.jetspeed.container.session.PortalSessionMonitor)
130: */
131: public void portalSessionDestroyed(PortalSessionMonitor psm) {
132: PortalSessionRegistry psr = (PortalSessionRegistry) portalSessionsRegistry
133: .remove(psm.getSessionId());
134: if (psr != null) {
135: // we iterate with shallow copy of paSessions to avoid conflicts with concurrent updates of paSessions
136: Iterator iter = valuesShallowCopy(
137: psr.sessionMonitors.values()).iterator();
138: while (iter.hasNext()) {
139: ((PortletApplicationSessionMonitor) iter.next())
140: .invalidateSession();
141: }
142:
143: try {
144: // To make sure its gone.
145: // You better not remove the psm from the portal session yourself ;)
146: psm.invalidateSession();
147: } catch (IllegalStateException ise) {
148: // pSession already invalid, ignore
149: }
150: }
151: }
152:
153: /* (non-Javadoc)
154: * @see org.apache.jetspeed.container.session.PortalSessionsManager#checkMonitorSession(java.lang.String, javax.servlet.http.HttpSession, javax.servlet.http.HttpSession)
155: */
156: public void checkMonitorSession(String contextPath,
157: HttpSession portalSession, HttpSession paSession) {
158: if (portalSession != null && paSession != null) {
159: if (portalSession == paSession) {
160: // On WebSphere 6.1.0.11, strange symptoms like this occur...
161: log.warn("servlet context name of paSession("
162: + paSession.getId()
163: + "): "
164: + paSession.getServletContext()
165: .getServletContextName());
166: return;
167: }
168:
169: PortalSessionRegistry psr = (PortalSessionRegistry) portalSessionsRegistry
170: .get(portalSession.getId());
171: if (psr == null) {
172: // yet unexplained condition: the HttpSessionListener on the portal application *should* have registered the session!!!
173: // Alas, it has been reported to happen...
174: // Now trying to do some recovering here
175: PortalSessionMonitor psm = (PortalSessionMonitor) portalSession
176: .getAttribute(PortalSessionMonitor.SESSION_KEY);
177: // the psm better be null here, otherwise something really is corrupt or not playing by the listeners contracts
178: if (psm == null) {
179: portalSessionCreated(portalSession);
180: } else {
181: // Now we have discovered a really strange situation here
182: // Only explanation I can see is that a passivation of the portalSession occurred,
183: // but that the activation again didn't trigger the sessionDidActivate event handler???
184: // Lets just try to accomodate this situation for now:
185: portalSessionDidActivate(psm);
186: }
187: // now retrieve the just created psr again
188: psr = (PortalSessionRegistry) portalSessionsRegistry
189: .get(portalSession.getId());
190: }
191: PortletApplicationSessionMonitor pasm = (PortletApplicationSessionMonitor) psr.sessionMonitors
192: .get(contextPath);
193: if (pasm != null) {
194: try {
195: if (paSession
196: .getAttribute(PortletApplicationSessionMonitor.SESSION_KEY) == null) {
197: // looks like Client didn't join the previous pa session
198: // destroy the "old" paSession
199: pasm.invalidateSession();
200: pasm = null;
201: // no need to remove the "old" pasm from the sessionMonitors as it will be replaced right below
202: }
203: } catch (IllegalStateException ise) {
204: // paSession already invalid, ignore
205: }
206: }
207: if (pasm == null) {
208: pasm = new PortletApplicationSessionMonitorImpl(
209: contextPath, portalSession.getId(),
210: psr.portalSessionKey, forceInvalidate);
211: try {
212: paSession
213: .setAttribute(
214: PortletApplicationSessionMonitor.SESSION_KEY,
215: pasm);
216: psr.sessionMonitors.put(contextPath, pasm);
217: } catch (IllegalStateException ise) {
218: // paSession already invalid, ignore
219: }
220: }
221: }
222: }
223:
224: /* (non-Javadoc)
225: * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionWillPassivate(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)
226: */
227: public void sessionWillPassivate(
228: PortletApplicationSessionMonitor pasm) {
229: PortalSessionRegistry psr = (PortalSessionRegistry) portalSessionsRegistry
230: .get(pasm.getPortalSessionId());
231: if (psr != null) {
232: psr.sessionMonitors.remove(pasm.getContextPath());
233: }
234: }
235:
236: /* (non-Javadoc)
237: * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionDidActivate(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)
238: */
239: public void sessionDidActivate(
240: PortletApplicationSessionMonitor restoredPasm) {
241: PortalSessionRegistry psr = (PortalSessionRegistry) portalSessionsRegistry
242: .get(restoredPasm.getPortalSessionId());
243: if (psr == null) {
244: // looks like the portalSession was passivated or the paSession was replicated to another JVM while its related portalSession wasn't (yet)
245: // so, we're gonna anticipate future activation of the portalSession:
246: // create a temporary psr with an "empty" psm for now (portalSessionKey == -1)
247: // once the portalSession is replicated/Activated, it will validate registered paSessions having the correct portalSessionKey
248: psr = new PortalSessionRegistry();
249: psr.psm = new PortalSessionMonitorImpl(-1);
250: portalSessionsRegistry.put(restoredPasm
251: .getPortalSessionId(), psr);
252: }
253:
254: // save the restored instance
255: restoredPasm.getSession().setAttribute(
256: PortletApplicationSessionMonitor.SESSION_KEY,
257: restoredPasm);
258: psr.sessionMonitors.put(restoredPasm.getContextPath(),
259: restoredPasm);
260: }
261:
262: /* (non-Javadoc)
263: * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionDestroyed(org.apache.jetspeed.container.session.PortletApplicationSessionMonitor)
264: */
265: public void sessionDestroyed(PortletApplicationSessionMonitor pasm) {
266: PortalSessionRegistry psr = (PortalSessionRegistry) portalSessionsRegistry
267: .get(pasm.getPortalSessionId());
268: if (psr != null) {
269: psr.sessionMonitors.remove(pasm.getContextPath());
270:
271: try {
272: // To make sure its gone.
273: // You better not remove the pasm from the session yourself ;)
274: pasm.invalidateSession();
275: } catch (IllegalStateException ise) {
276: // paSession already invalid, ignore
277: }
278: }
279: }
280:
281: /* (non-Javadoc)
282: * @see org.apache.jetspeed.container.session.PortalSessionsManager#sessionCount()
283: */
284: public int sessionCount() {
285:
286: return portalSessionsRegistry.size();
287: }
288:
289: /**
290: * Returns a shallow copy of the given Collection.
291: * @param inValues
292: * @return shallow copy
293: */
294: private Collection valuesShallowCopy(Collection inValues) {
295: return Arrays.asList(inValues.toArray());
296: }
297: }
|