001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.servlet;
016    
017    import com.liferay.portal.kernel.concurrent.ConcurrentHashSet;
018    import com.liferay.portal.kernel.servlet.filters.compoundsessionid.CompoundSessionIdSplitterUtil;
019    
020    import java.io.Serializable;
021    
022    import java.util.Set;
023    import java.util.concurrent.ConcurrentHashMap;
024    import java.util.concurrent.ConcurrentMap;
025    
026    import javax.servlet.http.HttpSession;
027    import javax.servlet.http.HttpSessionBindingEvent;
028    import javax.servlet.http.HttpSessionBindingListener;
029    import javax.servlet.http.HttpSessionEvent;
030    import javax.servlet.http.HttpSessionListener;
031    
032    /**
033     * <p>
034     * See http://issues.liferay.com/browse/LEP-1466.
035     * </p>
036     *
037     * @author Rudy Hilado
038     * @author Shuyang Zhou
039     */
040    public class PortletSessionTracker
041            implements HttpSessionListener, HttpSessionBindingListener, Serializable {
042    
043            public static void add(HttpSession session) {
044                    _instance._add(session);
045            }
046    
047            public static HttpSessionBindingListener getInstance() {
048                    return _instance;
049            }
050    
051            public static void invalidate(HttpSession session) {
052                    _instance._invalidate(session.getId());
053            }
054    
055            public static void invalidate(String sessionId) {
056                    _instance._invalidate(sessionId);
057            }
058    
059            public void sessionCreated(HttpSessionEvent httpSessionEvent) {
060            }
061    
062            public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
063                    _invalidate(httpSessionEvent.getSession().getId());
064            }
065    
066            public void valueBound(HttpSessionBindingEvent event) {
067            }
068    
069            public void valueUnbound(HttpSessionBindingEvent event) {
070                    invalidate(event.getSession().getId());
071            }
072    
073            private PortletSessionTracker() {
074                    _sessions = new ConcurrentHashMap<String, Set<HttpSession>>();
075    
076                    PortletSessionListenerManager.addHttpSessionListener(this);
077            }
078    
079            private void _add(HttpSession session) {
080                    String sessionId = session.getId();
081    
082                    if (CompoundSessionIdSplitterUtil.hasSessionDelimiter()) {
083                            sessionId = CompoundSessionIdSplitterUtil.parseSessionId(sessionId);
084                    }
085    
086                    Set<HttpSession> sessions = _sessions.get(sessionId);
087    
088                    if (sessions == null) {
089                            sessions = new ConcurrentHashSet<HttpSession>();
090    
091                            Set<HttpSession> previousSessions = _sessions.putIfAbsent(
092                                    sessionId, sessions);
093    
094                            if (previousSessions != null) {
095                                    sessions = previousSessions;
096                            }
097                    }
098    
099                    sessions.add(session);
100            }
101    
102            private void _invalidate(String sessionId) {
103                    if (CompoundSessionIdSplitterUtil.hasSessionDelimiter()) {
104                            sessionId = CompoundSessionIdSplitterUtil.parseSessionId(sessionId);
105                    }
106    
107                    Set<HttpSession> sessions = _sessions.remove(sessionId);
108    
109                    if (sessions == null) {
110                            return;
111                    }
112    
113                    for (HttpSession session : sessions) {
114                            try {
115                                    session.invalidate();
116                            }
117                            catch (Exception e) {
118                            }
119                    }
120            }
121    
122            private static PortletSessionTracker _instance =
123                    new PortletSessionTracker();
124    
125            private transient ConcurrentMap<String, Set<HttpSession>> _sessions;
126    
127    }