001    /**
002     * Copyright (c) 2000-2013 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            @Override
060            public void sessionCreated(HttpSessionEvent httpSessionEvent) {
061            }
062    
063            @Override
064            public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
065                    _invalidate(httpSessionEvent.getSession().getId());
066            }
067    
068            @Override
069            public void valueBound(HttpSessionBindingEvent event) {
070            }
071    
072            @Override
073            public void valueUnbound(HttpSessionBindingEvent event) {
074                    invalidate(event.getSession().getId());
075            }
076    
077            private PortletSessionTracker() {
078                    _sessions = new ConcurrentHashMap<String, Set<HttpSession>>();
079    
080                    PortletSessionListenerManager.addHttpSessionListener(this);
081            }
082    
083            private void _add(HttpSession session) {
084                    String sessionId = session.getId();
085    
086                    if (CompoundSessionIdSplitterUtil.hasSessionDelimiter()) {
087                            sessionId = CompoundSessionIdSplitterUtil.parseSessionId(sessionId);
088                    }
089    
090                    Set<HttpSession> sessions = _sessions.get(sessionId);
091    
092                    if (sessions == null) {
093                            sessions = new ConcurrentHashSet<HttpSession>();
094    
095                            Set<HttpSession> previousSessions = _sessions.putIfAbsent(
096                                    sessionId, sessions);
097    
098                            if (previousSessions != null) {
099                                    sessions = previousSessions;
100                            }
101                    }
102    
103                    sessions.add(session);
104            }
105    
106            private void _invalidate(String sessionId) {
107                    if (CompoundSessionIdSplitterUtil.hasSessionDelimiter()) {
108                            sessionId = CompoundSessionIdSplitterUtil.parseSessionId(sessionId);
109                    }
110    
111                    Set<HttpSession> sessions = _sessions.remove(sessionId);
112    
113                    if (sessions == null) {
114                            return;
115                    }
116    
117                    for (HttpSession session : sessions) {
118                            try {
119                                    session.invalidate();
120                            }
121                            catch (Exception e) {
122                            }
123                    }
124            }
125    
126            private static PortletSessionTracker _instance =
127                    new PortletSessionTracker();
128    
129            private transient ConcurrentMap<String, Set<HttpSession>> _sessions;
130    
131    }