All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.server.session.AbstractSessionManager Maven / Gradle / Ivy

There is a newer version: 1.0-rc5
Show newest version
// ========================================================================
// Copyright (c) 1999-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at 
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses. 
// ========================================================================

package org.eclipse.jetty.server.session;

import static java.lang.Math.round;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.statistic.CounterStatistic;
import org.eclipse.jetty.util.statistic.SampleStatistic;

/* ------------------------------------------------------------ */
/**
 * An Abstract implementation of SessionManager. The partial implementation of
 * SessionManager interface provides the majority of the handling required to
 * implement a SessionManager. Concrete implementations of SessionManager based
 * on AbstractSessionManager need only implement the newSession method to return
 * a specialised version of the Session inner class that provides an attribute
 * Map.
 * 

* */ public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager { public Set __defaultSessionTrackingModes = Collections.unmodifiableSet( new HashSet( Arrays.asList(new SessionTrackingMode[]{SessionTrackingMode.COOKIE,SessionTrackingMode.URL}))); /* ------------------------------------------------------------ */ public final static int __distantFuture=60*60*24*7*52*20; private static final HttpSessionContext __nullSessionContext=new NullSessionContext(); /* ------------------------------------------------------------ */ // Setting of max inactive interval for new sessions // -1 means no timeout protected int _dftMaxIdleSecs=-1; protected SessionHandler _sessionHandler; protected boolean _httpOnly=false; protected SessionIdManager _sessionIdManager; protected boolean _secureCookies=false; protected Object _sessionAttributeListeners; protected Object _sessionListeners; protected ClassLoader _loader; protected ContextHandler.Context _context; protected String _sessionCookie=__DefaultSessionCookie; protected String _sessionIdPathParameterName = __DefaultSessionIdPathParameterName; protected String _sessionIdPathParameterNamePrefix =";"+ _sessionIdPathParameterName +"="; protected String _sessionDomain; protected String _sessionPath; protected int _maxCookieAge=-1; protected int _refreshCookieAge; protected boolean _nodeIdInSessionId; protected boolean _checkingRemoteSessionIdEncoding; protected String _sessionComment; public Set _sessionTrackingModes; private boolean _usingCookies; private boolean _usingURLs; protected final CounterStatistic _sessionsStats = new CounterStatistic(); protected final SampleStatistic _sessionTimeStats = new SampleStatistic(); /* ------------------------------------------------------------ */ public AbstractSessionManager() { setSessionTrackingModes(__defaultSessionTrackingModes); } /* ------------------------------------------------------------ */ public HttpCookie access(HttpSession session,boolean secure) { long now=System.currentTimeMillis(); Session s = ((SessionIf)session).getSession(); s.access(now); // Do we need to refresh the cookie? if (isUsingCookies() && (s.isIdChanged() || (getSessionCookieConfig().getMaxAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge())) ) ) { HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure); s.cookieSet(); s.setIdChanged(false); return cookie; } return null; } /* ------------------------------------------------------------ */ public void addEventListener(EventListener listener) { if (listener instanceof HttpSessionAttributeListener) _sessionAttributeListeners=LazyList.add(_sessionAttributeListeners,listener); if (listener instanceof HttpSessionListener) _sessionListeners=LazyList.add(_sessionListeners,listener); } /* ------------------------------------------------------------ */ public void clearEventListeners() { _sessionAttributeListeners=null; _sessionListeners=null; } /* ------------------------------------------------------------ */ public void complete(HttpSession session) { Session s = ((SessionIf)session).getSession(); s.complete(); } /* ------------------------------------------------------------ */ @Override public void doStart() throws Exception { _context=ContextHandler.getCurrentContext(); _loader=Thread.currentThread().getContextClassLoader(); if (_sessionIdManager==null) { final Server server=getSessionHandler().getServer(); synchronized (server) { _sessionIdManager=server.getSessionIdManager(); if (_sessionIdManager==null) { _sessionIdManager=new HashSessionIdManager(); server.setSessionIdManager(_sessionIdManager); } } } if (!_sessionIdManager.isStarted()) _sessionIdManager.start(); // Look for a session cookie name if (_context!=null) { String tmp=_context.getInitParameter(SessionManager.__SessionCookieProperty); if (tmp!=null) _sessionCookie=tmp; tmp=_context.getInitParameter(SessionManager.__SessionIdPathParameterNameProperty); if (tmp!=null) setSessionIdPathParameterName(tmp); // set up the max session cookie age if it isn't already if (_maxCookieAge==-1) { tmp=_context.getInitParameter(SessionManager.__MaxAgeProperty); if (tmp!=null) _maxCookieAge=Integer.parseInt(tmp.trim()); } // set up the session domain if it isn't already if (_sessionDomain==null) _sessionDomain=_context.getInitParameter(SessionManager.__SessionDomainProperty); // set up the sessionPath if it isn't already if (_sessionPath==null) _sessionPath=_context.getInitParameter(SessionManager.__SessionPathProperty); tmp=_context.getInitParameter(SessionManager.__CheckRemoteSessionEncoding); if (tmp!=null) _checkingRemoteSessionIdEncoding=Boolean.parseBoolean(tmp); } super.doStart(); } /* ------------------------------------------------------------ */ @Override public void doStop() throws Exception { super.doStop(); invalidateSessions(); _loader=null; } /* ------------------------------------------------------------ */ /** * @return Returns the httpOnly. */ public boolean getHttpOnly() { return _httpOnly; } /* ------------------------------------------------------------ */ public HttpSession getHttpSession(String nodeId) { String cluster_id = getIdManager().getClusterId(nodeId); Session session = getSession(cluster_id); if (session!=null && !session.getNodeId().equals(nodeId)) session.setIdChanged(true); return session; } /* ------------------------------------------------------------ */ /** * @return Returns the metaManager used for cross context session management */ public SessionIdManager getIdManager() { return _sessionIdManager; } /* ------------------------------------------------------------ */ /** * @return seconds */ @Override public int getMaxInactiveInterval() { return _dftMaxIdleSecs; } /* ------------------------------------------------------------ */ /** * @see #getSessionsMax() */ @Deprecated public int getMaxSessions() { return getSessionsMax(); } /* ------------------------------------------------------------ */ /** * @return maximum number of sessions */ public int getSessionsMax() { return (int)_sessionsStats.getMax(); } /* ------------------------------------------------------------ */ /** * @return total number of sessions */ public int getSessionsTotal() { return (int)_sessionsStats.getTotal(); } /* ------------------------------------------------------------ */ /** * @deprecated use {@link #getIdManager()} */ @Deprecated public SessionIdManager getMetaManager() { return getIdManager(); } /* ------------------------------------------------------------ */ /** * @deprecated always returns 0. no replacement available. */ @Deprecated public int getMinSessions() { return 0; } /* ------------------------------------------------------------ */ public int getRefreshCookieAge() { return _refreshCookieAge; } /* ------------------------------------------------------------ */ public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure) { if (isUsingCookies()) { String sessionPath = (_sessionPath==null) ? contextPath : _sessionPath; sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath; String id = getNodeId(session); HttpCookie cookie = null; if (_sessionComment == null) { cookie = new HttpCookie( _sessionCookie, id, _sessionDomain, sessionPath, _cookieConfig.getMaxAge(), _cookieConfig.isHttpOnly(), _cookieConfig.isSecure()); } else { cookie = new HttpCookie( _sessionCookie, id, _sessionDomain, sessionPath, _cookieConfig.getMaxAge(), _cookieConfig.isHttpOnly(), _cookieConfig.isSecure(), _sessionComment, 1); } return cookie; } return null; } /* ------------------------------------------------------------ */ /** * @return Returns the sessionHandler. */ public SessionHandler getSessionHandler() { return _sessionHandler; } /* ------------------------------------------------------------ */ /** * @deprecated Need to review if it is needed. */ public abstract Map getSessionMap(); /* ------------------------------------------------------------ */ public int getSessions() { return (int)_sessionsStats.getCurrent(); } /* ------------------------------------------------------------ */ public String getSessionIdPathParameterName() { return _sessionIdPathParameterName; } /* ------------------------------------------------------------ */ public String getSessionIdPathParameterNamePrefix() { return _sessionIdPathParameterNamePrefix; } /* ------------------------------------------------------------ */ public boolean isValid(HttpSession session) { Session s = ((SessionIf)session).getSession(); return s.isValid(); } /* ------------------------------------------------------------ */ public String getClusterId(HttpSession session) { Session s = ((SessionIf)session).getSession(); return s.getClusterId(); } /* ------------------------------------------------------------ */ public String getNodeId(HttpSession session) { Session s = ((SessionIf)session).getSession(); return s.getNodeId(); } /* ------------------------------------------------------------ */ /** * Create a new HttpSession for a request */ public HttpSession newHttpSession(HttpServletRequest request) { Session session=newSession(request); session.setMaxInactiveInterval(_dftMaxIdleSecs); addSession(session,true); return session; } /* ------------------------------------------------------------ */ public void removeEventListener(EventListener listener) { if (listener instanceof HttpSessionAttributeListener) _sessionAttributeListeners=LazyList.remove(_sessionAttributeListeners,listener); if (listener instanceof HttpSessionListener) _sessionListeners=LazyList.remove(_sessionListeners,listener); } /* ------------------------------------------------------------ */ /** * @see #statsReset() */ @Deprecated public void resetStats() { statsReset(); } /* ------------------------------------------------------------ */ /** * Reset statistics values */ public void statsReset() { _sessionsStats.reset(getSessions()); _sessionTimeStats.reset(); } /* ------------------------------------------------------------ */ /** * @param httpOnly * The httpOnly to set. */ public void setHttpOnly(boolean httpOnly) { _httpOnly=httpOnly; } /* ------------------------------------------------------------ */ /** * @param metaManager The metaManager used for cross context session management. */ public void setIdManager(SessionIdManager metaManager) { _sessionIdManager=metaManager; } /* ------------------------------------------------------------ */ /** * @param seconds */ public void setMaxInactiveInterval(int seconds) { _dftMaxIdleSecs=seconds; } /* ------------------------------------------------------------ */ public void setRefreshCookieAge(int ageInSeconds) { _refreshCookieAge=ageInSeconds; } /* ------------------------------------------------------------ */ /** * Set if the session manager should use SecureCookies. * A secure cookie will only be sent by a browser on a secure (https) connection to * avoid the concern of cookies being intercepted on non secure channels. * For the cookie to be issued as secure, the {@link ServletRequest#isSecure()} method must return true. * If SSL offload is used, then the {@link AbstractConnector#customize(org.eclipse.jetty.io.EndPoint, Request) * method can be used to force the request to be https, or the {@link AbstractConnector#setForwarded(boolean)} * can be set to true, so that the X-Forwarded-Proto header is respected. *

* If secure session cookies are used, then a session may not be shared between http and https requests. * * @param secureCookies If true, use secure cookies. */ public void setSecureCookies(boolean secureCookies) { _secureCookies=secureCookies; } public void setSessionCookie(String cookieName) { _sessionCookie=cookieName; } public void setSessionDomain(String domain) { _sessionDomain=domain; } /* ------------------------------------------------------------ */ /** * @param sessionHandler * The sessionHandler to set. */ public void setSessionHandler(SessionHandler sessionHandler) { _sessionHandler=sessionHandler; } /* ------------------------------------------------------------ */ public void setSessionIdPathParameterName(String param) { _sessionIdPathParameterName =(param==null||"none".equals(param))?null:param; _sessionIdPathParameterNamePrefix =(param==null||"none".equals(param))?null:(";"+ _sessionIdPathParameterName +"="); } protected abstract void addSession(Session session); /* ------------------------------------------------------------ */ /** * Add the session Registers the session with this manager and registers the * session ID with the sessionIDManager; */ protected void addSession(Session session, boolean created) { synchronized (_sessionIdManager) { _sessionIdManager.addSession(session); addSession(session); } if (created) { _sessionsStats.increment(); if (_sessionListeners!=null) { HttpSessionEvent event=new HttpSessionEvent(session); for (int i=0; i0;) ((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionDestroyed(event); } } } /* ------------------------------------------------------------ */ protected abstract boolean removeSession(String idInCluster); /* ------------------------------------------------------------ */ /** * @return maximum amount of time session remained valid */ public long getSessionTimeMax() { return _sessionTimeStats.getMax(); } /* ------------------------------------------------------------ */ public Set getDefaultSessionTrackingModes() { return __defaultSessionTrackingModes; } /* ------------------------------------------------------------ */ public Set getEffectiveSessionTrackingModes() { return Collections.unmodifiableSet(_sessionTrackingModes); } /* ------------------------------------------------------------ */ @Override public void setSessionTrackingModes(Set sessionTrackingModes) { _sessionTrackingModes=new HashSet(sessionTrackingModes); _usingCookies=_sessionTrackingModes.contains(SessionTrackingMode.COOKIE); _usingURLs=_sessionTrackingModes.contains(SessionTrackingMode.URL); } /* ------------------------------------------------------------ */ @Override public boolean isUsingCookies() { return _usingCookies; } /* ------------------------------------------------------------ */ @Override public boolean isUsingURLs() { return _usingURLs; } /* ------------------------------------------------------------ */ public SessionCookieConfig getSessionCookieConfig() { return _cookieConfig; } /* ------------------------------------------------------------ */ private SessionCookieConfig _cookieConfig = new SessionCookieConfig() { @Override public String getComment() { return _sessionComment; } @Override public String getDomain() { return _sessionDomain; } @Override public int getMaxAge() { return _maxCookieAge; } @Override public String getName() { return _sessionCookie; } @Override public String getPath() { return _sessionPath; } @Override public boolean isHttpOnly() { return _httpOnly; } @Override public boolean isSecure() { return _secureCookies; } @Override public void setComment(String comment) { _sessionComment = comment; } @Override public void setDomain(String domain) { _sessionDomain=domain; } @Override public void setHttpOnly(boolean httpOnly) { _httpOnly=httpOnly; } @Override public void setMaxAge(int maxAge) { _maxCookieAge=maxAge; } @Override public void setName(String name) { _sessionCookie=name; } @Override public void setPath(String path) { _sessionPath=path; } @Override public void setSecure(boolean secure) { _secureCookies=secure; } }; /* ------------------------------------------------------------ */ /** * @return total amount of time all sessions remained valid */ public long getSessionTimeTotal() { return _sessionTimeStats.getTotal(); } /* ------------------------------------------------------------ */ /** * @return mean amount of time session remained valid */ public double getSessionTimeMean() { return _sessionTimeStats.getMean(); } /* ------------------------------------------------------------ */ /** * @return standard deviation of amount of time session remained valid */ public double getSessionTimeStdDev() { return _sessionTimeStats.getStdDev(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.SessionManager#isCheckingRemoteSessionIdEncoding() */ public boolean isCheckingRemoteSessionIdEncoding() { return _checkingRemoteSessionIdEncoding; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.SessionManager#setCheckingRemoteSessionIdEncoding(boolean) */ public void setCheckingRemoteSessionIdEncoding(boolean remote) { _checkingRemoteSessionIdEncoding=remote; } /* ------------------------------------------------------------ */ /** * Null returning implementation of HttpSessionContext * * */ public static class NullSessionContext implements HttpSessionContext { /* ------------------------------------------------------------ */ private NullSessionContext() { } /* ------------------------------------------------------------ */ /** * @deprecated From HttpSessionContext */ @Deprecated public Enumeration getIds() { return Collections.enumeration(Collections.EMPTY_LIST); } /* ------------------------------------------------------------ */ /** * @deprecated From HttpSessionContext */ @Deprecated public HttpSession getSession(String id) { return null; } } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /** * Interface that any session wrapper should implement so that * SessionManager may access the Jetty session implementation. * */ public interface SessionIf extends HttpSession { public Session getSession(); } /* ------------------------------------------------------------ */ /** * *

* Implements {@link javax.servlet.http.HttpSession} from the javax.servlet package. *

* * */ public abstract class Session implements SessionIf, Serializable { protected final String _clusterId; // ID unique within cluster protected final String _nodeId; // ID unique within node protected final Map _attributes=new HashMap(); protected boolean _idChanged; protected final long _created; protected long _cookieSet; protected long _accessed; protected long _lastAccessed; protected boolean _invalid; protected boolean _doInvalidate; protected long _maxIdleMs=_dftMaxIdleSecs>0?_dftMaxIdleSecs*1000:-1; protected boolean _newSession; protected int _requests; /* ------------------------------------------------------------- */ protected Session(HttpServletRequest request) { _newSession=true; _created=System.currentTimeMillis(); _clusterId=_sessionIdManager.newSessionId(request,_created); _nodeId=_sessionIdManager.getNodeId(_clusterId,request); _accessed=_created; _lastAccessed=_created; _requests=1; Log.debug("new session & id "+_nodeId+" "+_clusterId); } /* ------------------------------------------------------------- */ protected Session(long created, long accessed, String clusterId) { _created=created; _clusterId=clusterId; _nodeId=_sessionIdManager.getNodeId(_clusterId,null); _accessed=accessed; _lastAccessed=accessed; _requests=1; Log.debug("new session "+_nodeId+" "+_clusterId); } /* ------------------------------------------------------------- */ /** * @return True is the session is invalid or passivated. */ protected boolean isNotAvailable() { return _invalid; } /* ------------------------------------------------------------- */ public Session getSession() { return this; } /* ------------------------------------------------------------ */ public Object getAttribute(String name) { synchronized (Session.this) { if (isNotAvailable()) throw new IllegalStateException(); return _attributes.get(name); } } /* ------------------------------------------------------------ */ public Enumeration getAttributeNames() { synchronized (Session.this) { if (isNotAvailable()) throw new IllegalStateException(); List names=_attributes==null?Collections.EMPTY_LIST:new ArrayList(_attributes.keySet()); return Collections.enumeration(names); } } /* ------------------------------------------------------------- */ public long getCookieSetTime() { return _cookieSet; } /* ------------------------------------------------------------- */ public long getCreationTime() throws IllegalStateException { if (isNotAvailable()) throw new IllegalStateException(); return _created; } /* ------------------------------------------------------------ */ public String getId() throws IllegalStateException { return _nodeIdInSessionId?_nodeId:_clusterId; } /* ------------------------------------------------------------- */ protected String getNodeId() { return _nodeId; } /* ------------------------------------------------------------- */ protected String getClusterId() { return _clusterId; } /* ------------------------------------------------------------- */ public long getLastAccessedTime() throws IllegalStateException { if (isNotAvailable()) throw new IllegalStateException(); return _lastAccessed; } /* ------------------------------------------------------------- */ public int getMaxInactiveInterval() { if (isNotAvailable()) throw new IllegalStateException(); return (int)(_maxIdleMs/1000); } /* ------------------------------------------------------------ */ /* * @see javax.servlet.http.HttpSession#getServletContext() */ public ServletContext getServletContext() { return _context; } /* ------------------------------------------------------------- */ /** * @deprecated */ @Deprecated public HttpSessionContext getSessionContext() throws IllegalStateException { if (isNotAvailable()) throw new IllegalStateException(); return __nullSessionContext; } /* ------------------------------------------------------------- */ /** * @deprecated As of Version 2.2, this method is replaced by * {@link #getAttribute} */ @Deprecated public Object getValue(String name) throws IllegalStateException { return getAttribute(name); } /* ------------------------------------------------------------- */ /** * @deprecated As of Version 2.2, this method is replaced by * {@link #getAttributeNames} */ @Deprecated public String[] getValueNames() throws IllegalStateException { synchronized(Session.this) { if (isNotAvailable()) throw new IllegalStateException(); if (_attributes==null) return new String[0]; String[] a=new String[_attributes.size()]; return (String[])_attributes.keySet().toArray(a); } } /* ------------------------------------------------------------ */ protected void access(long time) { synchronized(Session.this) { if (!_invalid) { _newSession=false; _lastAccessed=_accessed; _accessed=time; if (_maxIdleMs>0 && _lastAccessed>0 && _lastAccessed + _maxIdleMs < time) { invalidate(); } else { _requests++; } } } } /* ------------------------------------------------------------ */ protected void complete() { synchronized(Session.this) { _requests--; if (_doInvalidate && _requests<=0 ) doInvalidate(); } } /* ------------------------------------------------------------- */ protected void timeout() throws IllegalStateException { // remove session from context and invalidate other sessions with same ID. removeSession(this,true); // Notify listeners and unbind values synchronized (Session.this) { if (!_invalid) { if (_requests<=0) doInvalidate(); else _doInvalidate=true; } } } /* ------------------------------------------------------------- */ public void invalidate() throws IllegalStateException { // remove session from context and invalidate other sessions with same ID. removeSession(this,true); doInvalidate(); } /* ------------------------------------------------------------- */ protected void doInvalidate() throws IllegalStateException { try { Log.debug("invalidate ",_clusterId); // Notify listeners and unbind values if (isNotAvailable()) throw new IllegalStateException(); while (_attributes!=null && _attributes.size()>0) { ArrayList keys; synchronized (Session.this) { keys=new ArrayList(_attributes.keySet()); } Iterator iter=keys.iterator(); while (iter.hasNext()) { String key=(String)iter.next(); Object value; synchronized (Session.this) { value=_attributes.remove(key); } unbindValue(key,value); if (_sessionAttributeListeners!=null) { HttpSessionBindingEvent event=new HttpSessionBindingEvent(this,key,value); for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy