001/*
002 *
003 * (C) Copyright 2006-2009 Nuxeo SAS (http://nuxeo.com/) and contributors.
004 *
005 * All rights reserved. This program and the accompanying materials
006 * are made available under the terms of the GNU Lesser General Public License
007 * (LGPL) version 2.1 which accompanies this distribution, and is available at
008 * http://www.gnu.org/licenses/lgpl.html
009 *
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * Lesser General Public License for more details.
014 *
015 * Contributors:
016 *     Nuxeo - initial API and implementation
017 *
018 * $Id$
019 */
020
021package org.nuxeo.ecm.platform.web.common.session;
022
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.List;
027import java.util.Map;
028import java.util.concurrent.ConcurrentHashMap;
029
030import javax.servlet.http.HttpServletRequest;
031import javax.servlet.http.HttpSession;
032
033import org.apache.commons.logging.Log;
034import org.apache.commons.logging.LogFactory;
035import org.nuxeo.runtime.management.counters.CounterHelper;
036
037/**
038 * Singleton used to keep track of all HttpSessions. This Singleton is populated/updated either via the
039 * HttpSessionListener or via directedly via the Authentication filter
040 *
041 * @author Tiry (tdelprat@nuxeo.com)
042 * @since 5.4.2
043 */
044public class NuxeoHttpSessionMonitor {
045
046    public static final String REQUEST_COUNTER = "org.nuxeo.web.requests";
047
048    public static final String SESSION_COUNTER = "org.nuxeo.web.sessions";
049
050    public static final long REQUEST_COUNTER_STEP = 5;
051
052    protected static final Log log = LogFactory.getLog(NuxeoHttpSessionMonitor.class);
053
054    protected static NuxeoHttpSessionMonitor instance = new NuxeoHttpSessionMonitor();
055
056    protected long globalRequestCounter;
057
058    public static NuxeoHttpSessionMonitor instance() {
059        return instance;
060    }
061
062    protected Map<String, SessionInfo> sessionTracker = new ConcurrentHashMap<String, SessionInfo>();
063
064    protected void increaseRequestCounter() {
065        globalRequestCounter += 1;
066        if (globalRequestCounter == 1 || globalRequestCounter % REQUEST_COUNTER_STEP == 0) {
067            CounterHelper.setCounterValue(REQUEST_COUNTER, globalRequestCounter);
068        }
069    }
070
071    public SessionInfo addEntry(HttpSession session) {
072        if (session == null || session.getId() == null) {
073            return null;
074        }
075        SessionInfo si = new SessionInfo(session.getId());
076        sessionTracker.put(session.getId(), si);
077        return si;
078    }
079
080    public SessionInfo associatedUser(HttpServletRequest request) {
081        HttpSession session = request.getSession(false);
082        if (session != null && session.getId() != null) {
083            SessionInfo si = sessionTracker.get(session.getId());
084            if (si == null) {
085                si = addEntry(session);
086            }
087            if (request.getUserPrincipal() != null && si.getLoginName() == null) {
088                si.setLoginName(request.getUserPrincipal().getName());
089                CounterHelper.increaseCounter(SESSION_COUNTER);
090            }
091            si.setLastAccessUrl(request.getRequestURI());
092            increaseRequestCounter();
093            return si;
094        }
095        return null;
096    }
097
098    public SessionInfo associatedUser(HttpSession session, String userName) {
099        if (session == null || session.getId() == null) {
100            return null;
101        }
102        SessionInfo si = sessionTracker.get(session.getId());
103        if (si == null) {
104            si = addEntry(session);
105        }
106        if (si.getLoginName() == null) {
107            si.setLoginName(userName);
108            CounterHelper.increaseCounter(SESSION_COUNTER);
109        }
110        return si;
111    }
112
113    public SessionInfo updateEntry(HttpServletRequest request) {
114        HttpSession session = request.getSession(false);
115        if (session != null && session.getId() != null) {
116            SessionInfo si = sessionTracker.get(session.getId());
117            if (si != null) {
118                si.updateLastAccessTime();
119                si.setLastAccessUrl(request.getRequestURI());
120                increaseRequestCounter();
121                return si;
122            } else {
123                return addEntry(session);
124            }
125        }
126        return null;
127    }
128
129    public void removeEntry(String sid) {
130        SessionInfo si = sessionTracker.remove(sid);
131        if (si != null && si.getLoginName() != null) {
132            CounterHelper.decreaseCounter(SESSION_COUNTER);
133        }
134    }
135
136    public Collection<SessionInfo> getTrackedSessions() {
137        return sessionTracker.values();
138    }
139
140    public List<SessionInfo> getSortedSessions() {
141
142        List<SessionInfo> sortedSessions = new ArrayList<SessionInfo>();
143        for (SessionInfo si : getTrackedSessions()) {
144            if (si.getLoginName() != null) {
145                sortedSessions.add(si);
146            }
147        }
148        Collections.sort(sortedSessions);
149        return sortedSessions;
150    }
151
152    public List<SessionInfo> getSortedSessions(long maxInactivity) {
153        List<SessionInfo> sortedSessions = new ArrayList<SessionInfo>();
154        for (SessionInfo si : getTrackedSessions()) {
155            if (si.getLoginName() != null && si.getInactivityInS() < maxInactivity) {
156                sortedSessions.add(si);
157            }
158        }
159        Collections.sort(sortedSessions);
160        return sortedSessions;
161    }
162
163    public long getGlobalRequestCounter() {
164        return globalRequestCounter;
165    }
166
167}