From c5489bd7b2d071b0e7b95cf327c604b3a3cb6015 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Fri, 23 Oct 2015 14:10:42 +1100 Subject: [PATCH] Renaming from temporary session.x package --- .../InfinispanSessionIdManager.java | 2 +- .../mongodb/jmx/MongoSessionManagerMBean.java | 4 +- .../authentication/LoginAuthenticator.java | 20 +- .../authentication/SessionAuthentication.java | 4 +- .../org/eclipse/jetty/server/Request.java | 16 +- .../org/eclipse/jetty/server/Response.java | 2 +- .../eclipse/jetty/server/SessionManager.java | 8 +- .../jetty/server/session/AbstractSession.java | 664 -------- .../{x => }/AbstractSessionDataStore.java | 4 +- .../session/AbstractSessionIdManager.java | 113 +- .../session/AbstractSessionManager.java | 1054 ------------- .../session/{x => }/AbstractSessionStore.java | 12 +- .../session/{x => }/AlwaysStaleStrategy.java | 4 +- .../session/{x => }/DatabaseAdaptor.java | 2 +- .../session/{x => }/FileSessionDataStore.java | 12 +- .../server/session/HashSessionIdManager.java | 164 +- .../server/session/HashSessionManager.java | 669 +-------- .../jetty/server/session/HashedSession.java | 286 ---- .../session/{x => }/JDBCSessionDataStore.java | 12 +- .../server/session/JDBCSessionIdManager.java | 1333 ++--------------- .../server/session/JDBCSessionManager.java | 1151 +------------- .../jetty/server/session/MemSession.java | 146 -- .../session/{x => }/MemorySessionStore.java | 14 +- .../session/{x => }/NeverStaleStrategy.java | 4 +- .../session/{x => }/NullSessionDataStore.java | 13 +- .../jetty/server/session/{x => }/Session.java | 10 +- .../server/session/{x => }/SessionData.java | 2 +- .../session/{x => }/SessionDataStore.java | 2 +- .../server/session/{x => }/SessionKey.java | 2 +- .../session/{x => }/SessionManager.java | 10 +- .../session/{x => }/SessionScavenger.java | 4 +- .../server/session/{x => }/SessionStore.java | 2 +- .../session/{x => }/StalePeriodStrategy.java | 4 +- .../session/{x => }/StalenessStrategy.java | 2 +- .../UnreadableSessionDataException.java | 2 +- .../UnwriteableSessionDataException.java | 2 +- ...gerMBean.java => SessionManagerMBean.java} | 10 +- .../session/x/AbstractSessionIdManager.java | 393 ----- .../session/x/HashSessionIdManager.java | 79 - .../server/session/x/HashSessionManager.java | 56 - .../session/x/JDBCSessionIdManager.java | 439 ------ .../server/session/x/JDBCSessionManager.java | 71 - .../eclipse/jetty/server/ResponseTest.java | 8 +- .../session/HashSessionManagerTest.java | 21 +- .../server/session/SessionCookieTest.java | 205 +-- 45 files changed, 499 insertions(+), 6538 deletions(-) delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/AbstractSessionDataStore.java (91%) delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/AbstractSessionStore.java (92%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/AlwaysStaleStrategy.java (86%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/DatabaseAdaptor.java (99%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/FileSessionDataStore.java (92%) delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/JDBCSessionDataStore.java (98%) delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/MemorySessionStore.java (88%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/NeverStaleStrategy.java (86%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/NullSessionDataStore.java (76%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/Session.java (98%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/SessionData.java (99%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/SessionDataStore.java (98%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/SessionKey.java (98%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/SessionManager.java (99%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/SessionScavenger.java (97%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/SessionStore.java (97%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/StalePeriodStrategy.java (91%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/StalenessStrategy.java (95%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/UnreadableSessionDataException.java (96%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/{x => }/UnwriteableSessionDataException.java (96%) rename jetty-server/src/main/java/org/eclipse/jetty/server/session/jmx/{AbstractSessionManagerMBean.java => SessionManagerMBean.java} (84%) delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionIdManager.java delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/x/HashSessionIdManager.java delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/x/HashSessionManager.java delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionIdManager.java delete mode 100644 jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionManager.java diff --git a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java index 35be47ee324..c5fb6d0b591 100644 --- a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java +++ b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionIdManager.java @@ -138,7 +138,7 @@ public class InfinispanSessionIdManager extends AbstractSessionIdManager if (id == null) return false; - String clusterId = getClusterId(id); + String clusterId = getId(id); //ask the cluster - this should also tickle the idle expiration timer on the sessionid entry //keeping it valid diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java index 58a2b448d60..1bef5d4b3ae 100644 --- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java +++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java @@ -22,11 +22,11 @@ import org.eclipse.jetty.nosql.mongodb.MongoSessionManager; import org.eclipse.jetty.server.handler.AbstractHandlerContainer; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.server.session.jmx.AbstractSessionManagerMBean; +import org.eclipse.jetty.server.session.jmx.SessionManagerMBean; import org.eclipse.jetty.util.annotation.ManagedObject; @ManagedObject("Mongo Session Manager MBean") -public class MongoSessionManagerMBean extends AbstractSessionManagerMBean +public class MongoSessionManagerMBean extends SessionManagerMBean { public MongoSessionManagerMBean(Object managedObject) diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java index e85b680fbef..63d41a0d46b 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java @@ -29,7 +29,7 @@ import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; import org.eclipse.jetty.server.UserIdentity; -import org.eclipse.jetty.server.session.AbstractSession; +import org.eclipse.jetty.server.session.Session; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -109,17 +109,17 @@ public abstract class LoginAuthenticator implements Authenticator { //if we should renew sessions, and there is an existing session that may have been seen by non-authenticated users //(indicated by SESSION_SECURED not being set on the session) then we should change id - if (httpSession.getAttribute(AbstractSession.SESSION_CREATED_SECURE)!=Boolean.TRUE) + if (httpSession.getAttribute(Session.SESSION_CREATED_SECURE)!=Boolean.TRUE) { - if (httpSession instanceof AbstractSession) + if (httpSession instanceof Session) { - AbstractSession abstractSession = (AbstractSession)httpSession; - String oldId = abstractSession.getId(); - abstractSession.renewId(request); - abstractSession.setAttribute(AbstractSession.SESSION_CREATED_SECURE, Boolean.TRUE); - if (abstractSession.isIdChanged() && response != null && (response instanceof Response)) - ((Response)response).addCookie(abstractSession.getSessionManager().getSessionCookie(abstractSession, request.getContextPath(), request.isSecure())); - LOG.debug("renew {}->{}",oldId,abstractSession.getId()); + Session s = (Session)httpSession; + String oldId = s.getId(); + s.renewId(request); + s.setAttribute(Session.SESSION_CREATED_SECURE, Boolean.TRUE); + if (s.isIdChanged() && response != null && (response instanceof Response)) + ((Response)response).addCookie(s.getSessionManager().getSessionCookie(s, request.getContextPath(), request.isSecure())); + LOG.debug("renew {}->{}",oldId,s.getId()); } else LOG.warn("Unable to renew session "+httpSession); diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java index 3a7c006b51b..6c9681a8589 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java @@ -33,7 +33,7 @@ import org.eclipse.jetty.security.AbstractUserAuthentication; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.server.UserIdentity; -import org.eclipse.jetty.server.session.AbstractSession; +import org.eclipse.jetty.server.session.Session; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -89,7 +89,7 @@ public class SessionAuthentication extends AbstractUserAuthentication implements if (security!=null) security.logout(this); if (_session!=null) - _session.removeAttribute(AbstractSession.SESSION_CREATED_SECURE); + _session.removeAttribute(Session.SESSION_CREATED_SECURE); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 2b325694337..1f21e630890 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -76,7 +76,7 @@ import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler.Context; -import org.eclipse.jetty.server.session.AbstractSession; +import org.eclipse.jetty.server.session.Session; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.IO; @@ -1494,14 +1494,14 @@ public class Request implements HttpServletRequest if (session == null) throw new IllegalStateException("No session"); - if (session instanceof AbstractSession) + if (session instanceof Session) { - AbstractSession abstractSession = ((AbstractSession)session); - abstractSession.renewId(this); + Session s = ((Session)session); + s.renewId(this); if (getRemoteUser() != null) - abstractSession.setAttribute(AbstractSession.SESSION_CREATED_SECURE, Boolean.TRUE); - if (abstractSession.isIdChanged()) - _channel.getResponse().addCookie(_sessionManager.getSessionCookie(abstractSession, getContextPath(), isSecure())); + s.setAttribute(Session.SESSION_CREATED_SECURE, Boolean.TRUE); + if (s.isIdChanged()) + _channel.getResponse().addCookie(_sessionManager.getSessionCookie(s, getContextPath(), isSecure())); } return session.getId(); @@ -1697,7 +1697,7 @@ public class Request implements HttpServletRequest return false; HttpSession session = getSession(false); - return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session))); + return (session != null && _sessionManager.getSessionIdManager().getId(_requestedSessionId).equals(_sessionManager.getId(session))); } /* ------------------------------------------------------------ */ diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 4b91a87bc5f..86d5341e51f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -449,7 +449,7 @@ public class Response implements HttpServletResponse if (!sessionManager.isValid(session)) return url; - String id = sessionManager.getNodeId(session); + String id = sessionManager.getExtendedId(session); if (uri == null) uri = new HttpURI(url); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java index 35b9bab6137..cfef6a4f098 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java @@ -216,17 +216,17 @@ public interface SessionManager extends LifeCycle /** * @param session the session object * @return the unique id of the session within the cluster, extended with an optional node id. - * @see #getClusterId(HttpSession) + * @see #getId(HttpSession) */ - public String getNodeId(HttpSession session); + public String getExtendedId(HttpSession session); /* ------------------------------------------------------------ */ /** * @param session the session object * @return the unique id of the session within the cluster (without a node id extension) - * @see #getNodeId(HttpSession) + * @see #getExtendedId(HttpSession) */ - public String getClusterId(HttpSession session); + public String getId(HttpSession session); /* ------------------------------------------------------------ */ /** diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java deleted file mode 100644 index 046ef35a934..00000000000 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java +++ /dev/null @@ -1,664 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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 java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSessionActivationListener; -import javax.servlet.http.HttpSessionBindingEvent; -import javax.servlet.http.HttpSessionBindingListener; -import javax.servlet.http.HttpSessionContext; -import javax.servlet.http.HttpSessionEvent; - -import org.eclipse.jetty.server.SessionManager; -import org.eclipse.jetty.util.log.Logger; - -/** - * - *

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

- * - */ -@SuppressWarnings("deprecation") -public abstract class AbstractSession implements AbstractSessionManager.SessionIf -{ - final static Logger LOG = SessionHandler.LOG; - public final static String SESSION_CREATED_SECURE="org.eclipse.jetty.security.sessionCreatedSecure"; - private String _clusterId; // ID without any node (ie "worker") id appended - private String _nodeId; // ID of session with node(ie "worker") id appended - private final AbstractSessionManager _manager; - private boolean _idChanged; - private final long _created; - private long _cookieSet; - private long _accessed; // the time of the last access - private long _lastAccessed; // the time of the last access excluding this one - private boolean _invalid; - private boolean _doInvalidate; - private long _maxIdleMs; - private boolean _newSession; - private int _requests; - - - - /* ------------------------------------------------------------- */ - protected AbstractSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request) - { - _manager = abstractSessionManager; - - _newSession=true; - _created=System.currentTimeMillis(); - _clusterId=_manager._sessionIdManager.newSessionId(request,_created); - _nodeId=_manager._sessionIdManager.getExtendedId(_clusterId,request); - _accessed=_created; - _lastAccessed=_created; - _requests=1; - _maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1; - if (LOG.isDebugEnabled()) - LOG.debug("new session & id "+_nodeId+" "+_clusterId); - } - - /* ------------------------------------------------------------- */ - protected AbstractSession(AbstractSessionManager abstractSessionManager, long created, long accessed, String clusterId) - { - _manager = abstractSessionManager; - _created=created; - _clusterId=clusterId; - _nodeId=_manager._sessionIdManager.getExtendedId(_clusterId,null); - _accessed=accessed; - _lastAccessed=accessed; - _requests=1; - _maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1; - if (LOG.isDebugEnabled()) - LOG.debug("new session "+_nodeId+" "+_clusterId); - } - - /* ------------------------------------------------------------- */ - /** - * asserts that the session is valid - * @throws IllegalStateException if the sesion is invalid - */ - protected void checkValid() throws IllegalStateException - { - if (_invalid) - throw new IllegalStateException(); - } - - /* ------------------------------------------------------------- */ - /** Check to see if session has expired as at the time given. - * @param time the time in milliseconds - * @return true if expired - */ - protected boolean checkExpiry(long time) - { - if (_maxIdleMs>0 && _lastAccessed>0 && _lastAccessed + _maxIdleMs < time) - return true; - return false; - } - - /* ------------------------------------------------------------- */ - @Override - public AbstractSession getSession() - { - return this; - } - - /* ------------------------------------------------------------- */ - public long getAccessed() - { - synchronized (this) - { - return _accessed; - } - } - - /* ------------------------------------------------------------- */ - public abstract Map getAttributeMap(); - - - - - - /* ------------------------------------------------------------ */ - public abstract int getAttributes(); - - - - - /* ------------------------------------------------------------ */ - public abstract Set getNames(); - - - /* ------------------------------------------------------------- */ - public long getCookieSetTime() - { - return _cookieSet; - } - - /* ------------------------------------------------------------- */ - public void setCookieSetTime(long time) - { - _cookieSet = time; - } - - /* ------------------------------------------------------------- */ - @Override - public long getCreationTime() throws IllegalStateException - { - checkValid(); - return _created; - } - - /* ------------------------------------------------------------ */ - @Override - public String getId() throws IllegalStateException - { - return _manager._nodeIdInSessionId?_nodeId:_clusterId; - } - - /* ------------------------------------------------------------- */ - public String getNodeId() - { - return _nodeId; - } - - /* ------------------------------------------------------------- */ - public String getClusterId() - { - return _clusterId; - } - - /* ------------------------------------------------------------- */ - @Override - public long getLastAccessedTime() throws IllegalStateException - { - checkValid(); - return _lastAccessed; - } - - /* ------------------------------------------------------------- */ - public void setLastAccessedTime(long time) - { - _lastAccessed = time; - } - - /* ------------------------------------------------------------- */ - @Override - public int getMaxInactiveInterval() - { - return (int)(_maxIdleMs/1000); - } - - /* ------------------------------------------------------------ */ - /* - * @see javax.servlet.http.HttpSession#getServletContext() - */ - @Override - public ServletContext getServletContext() - { - return _manager._context; - } - - /* ------------------------------------------------------------- */ - @Deprecated - @Override - public HttpSessionContext getSessionContext() throws IllegalStateException - { - checkValid(); - return AbstractSessionManager.__nullSessionContext; - } - - /* ------------------------------------------------------------- */ - /** - * @deprecated As of Version 2.2, this method is replaced by - * {@link #getAttribute} - */ - @Deprecated - @Override - public Object getValue(String name) throws IllegalStateException - { - return getAttribute(name); - } - - - - /* ------------------------------------------------------------ */ - public void renewId(HttpServletRequest request) - { - _manager._sessionIdManager.renewSessionId(getClusterId(), getNodeId(), request); - setIdChanged(true); - } - - /* ------------------------------------------------------------- */ - public SessionManager getSessionManager() - { - return _manager; - } - - /* ------------------------------------------------------------ */ - protected void setClusterId (String clusterId) - { - _clusterId = clusterId; - } - - /* ------------------------------------------------------------ */ - protected void setNodeId (String nodeId) - { - _nodeId = nodeId; - } - - - /* ------------------------------------------------------------ */ - protected boolean access(long time) - { - synchronized(this) - { - if (_invalid) - return false; - _newSession=false; - _lastAccessed=_accessed; - _accessed=time; - - if (checkExpiry(time)) - { - invalidate(); - return false; - } - _requests++; - return true; - } - } - - /* ------------------------------------------------------------ */ - protected void complete() - { - synchronized(this) - { - _requests--; - if (_doInvalidate && _requests<=0 ) - doInvalidate(); - } - } - - - /* ------------------------------------------------------------- */ - protected void timeout() throws IllegalStateException - { - // remove session from context and invalidate other sessions with same ID. - _manager.removeSession(this,true); - - // Notify listeners and unbind values - boolean do_invalidate=false; - synchronized (this) - { - if (!_invalid) - { - if (_requests<=0) - do_invalidate=true; - else - _doInvalidate=true; - } - } - if (do_invalidate) - doInvalidate(); - } - - /* ------------------------------------------------------------- */ - @Override - public void invalidate() throws IllegalStateException - { - checkValid(); - // remove session from context and invalidate other sessions with same ID. - _manager.removeSession(this,true); - doInvalidate(); - } - - /* ------------------------------------------------------------- */ - protected void doInvalidate() throws IllegalStateException - { - try - { - if (LOG.isDebugEnabled()) - LOG.debug("invalidate {}",_clusterId); - if (isValid()) - clearAttributes(); - } - finally - { - synchronized (this) - { - // mark as invalid - _invalid=true; - } - } - } - - /* ------------------------------------------------------------- */ - public abstract void clearAttributes(); - - - /* ------------------------------------------------------------- */ - public boolean isIdChanged() - { - return _idChanged; - } - - /* ------------------------------------------------------------- */ - @Override - public boolean isNew() throws IllegalStateException - { - checkValid(); - return _newSession; - } - - /* ------------------------------------------------------------- */ - /** - * @deprecated As of Version 2.2, this method is replaced by - * {@link #setAttribute} - */ - @Deprecated - @Override - public void putValue(java.lang.String name, java.lang.Object value) throws IllegalStateException - { - changeAttribute(name,value); - } - - /* ------------------------------------------------------------ */ - @Override - public void removeAttribute(String name) - { - setAttribute(name,null); - } - - /* ------------------------------------------------------------- */ - /** - * @deprecated As of Version 2.2, this method is replaced by - * {@link #removeAttribute} - */ - @Deprecated - @Override - public void removeValue(java.lang.String name) throws IllegalStateException - { - removeAttribute(name); - } - - /* ------------------------------------------------------------ */ - @Override - public Enumeration getAttributeNames() - { - synchronized (this) - { - checkValid(); - return doGetAttributeNames(); - } - } - - /* ------------------------------------------------------------- */ - /** - * @deprecated As of Version 2.2, this method is replaced by - * {@link #getAttributeNames} - */ - @Deprecated - @Override - public String[] getValueNames() throws IllegalStateException - { - synchronized(this) - { - checkValid(); - Enumeration anames = doGetAttributeNames(); - if (anames == null) - return new String[0]; - ArrayList names = new ArrayList(); - while (anames.hasMoreElements()) - names.add(anames.nextElement()); - return names.toArray(new String[names.size()]); - } - } - - - /* ------------------------------------------------------------ */ - public abstract Object doPutOrRemove(String name, Object value); - - - /* ------------------------------------------------------------ */ - public abstract Object doGet(String name); - - - /* ------------------------------------------------------------ */ - public abstract Enumeration doGetAttributeNames(); - - - /* ------------------------------------------------------------ */ - @Override - public Object getAttribute(String name) - { - synchronized (this) - { - checkValid(); - return doGet(name); - } - } - - - /* ------------------------------------------------------------ */ - @Override - public void setAttribute(String name, Object value) - { - changeAttribute(name,value); - } - - /* ------------------------------------------------------------ */ - /** - * @param name the name of the attribute - * @param value the value of the attribute - * @return true if attribute changed - * @deprecated use changeAttribute(String,Object) instead - */ - @Deprecated - protected boolean updateAttribute (String name, Object value) - { - Object old=null; - synchronized (this) - { - checkValid(); - old=doPutOrRemove(name,value); - } - - if (value==null || !value.equals(old)) - { - if (old!=null) - unbindValue(name,old); - if (value!=null) - bindValue(name,value); - - _manager.doSessionAttributeListeners(this,name,old,value); - return true; - } - return false; - } - - - /* ------------------------------------------------------------ */ - /** - * Either set (perhaps replace) or remove the value of the attribute - * in the session. The appropriate session attribute listeners are - * also called. - * - * @param name the name of the attribute - * @param value the value of the attribute - * @return the old value for the attribute - */ - protected Object changeAttribute (String name, Object value) - { - Object old=null; - synchronized (this) - { - checkValid(); - old=doPutOrRemove(name,value); - } - - callSessionAttributeListeners(name, value, old); - - return old; - } - - /* ------------------------------------------------------------ */ - /** - * Call binding and attribute listeners based on the new and old - * values of the attribute. - * - * @param name name of the attribute - * @param newValue new value of the attribute - * @param oldValue previous value of the attribute - */ - protected void callSessionAttributeListeners (String name, Object newValue, Object oldValue) - { - if (newValue==null || !newValue.equals(oldValue)) - { - if (oldValue!=null) - unbindValue(name,oldValue); - if (newValue!=null) - bindValue(name,newValue); - - _manager.doSessionAttributeListeners(this,name,oldValue,newValue); - } - } - - - /* ------------------------------------------------------------- */ - public void setIdChanged(boolean changed) - { - _idChanged=changed; - } - - /* ------------------------------------------------------------- */ - @Override - public void setMaxInactiveInterval(int secs) - { - _maxIdleMs=(long)secs*1000L; - } - - /* ------------------------------------------------------------- */ - @Override - public String toString() - { - return this.getClass().getName()+":"+getId()+"@"+hashCode(); - } - - /* ------------------------------------------------------------- */ - /** - * Bind value if value implements {@link HttpSessionBindingListener} (calls {@link HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)}) - * @param name the name with which the object is bound or unbound - * @param value the bound value - */ - public void bindValue(java.lang.String name, Object value) - { - if (value!=null&&value instanceof HttpSessionBindingListener) - ((HttpSessionBindingListener)value).valueBound(new HttpSessionBindingEvent(this,name)); - } - - /* ------------------------------------------------------------ */ - public boolean isValid() - { - return !_invalid; - } - - /* ------------------------------------------------------------- */ - protected void cookieSet() - { - synchronized (this) - { - _cookieSet=_accessed; - } - } - - /* ------------------------------------------------------------ */ - public int getRequests() - { - synchronized (this) - { - return _requests; - } - } - - /* ------------------------------------------------------------ */ - public void setRequests(int requests) - { - synchronized (this) - { - _requests=requests; - } - } - - /* ------------------------------------------------------------- */ - /** - * Unbind value if value implements {@link HttpSessionBindingListener} (calls {@link HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)}) - * @param name the name with which the object is bound or unbound - * @param value the bound value - */ - public void unbindValue(java.lang.String name, Object value) - { - if (value!=null&&value instanceof HttpSessionBindingListener) - ((HttpSessionBindingListener)value).valueUnbound(new HttpSessionBindingEvent(this,name)); - } - - /* ------------------------------------------------------------- */ - public void willPassivate() - { - synchronized(this) - { - HttpSessionEvent event = new HttpSessionEvent(this); - for (Iterator iter = getAttributeMap().values().iterator(); iter.hasNext();) - { - Object value = iter.next(); - if (value instanceof HttpSessionActivationListener) - { - HttpSessionActivationListener listener = (HttpSessionActivationListener) value; - listener.sessionWillPassivate(event); - } - } - } - } - - /* ------------------------------------------------------------- */ - public void didActivate() - { - synchronized(this) - { - HttpSessionEvent event = new HttpSessionEvent(this); - for (Iterator iter = getAttributeMap().values().iterator(); iter.hasNext();) - { - Object value = iter.next(); - if (value instanceof HttpSessionActivationListener) - { - HttpSessionActivationListener listener = (HttpSessionActivationListener) value; - listener.sessionDidActivate(event); - } - } - } - } - - -} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionDataStore.java similarity index 91% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionDataStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionDataStore.java index 737a599cf9f..90702c15931 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionDataStore.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import org.eclipse.jetty.server.handler.ContextHandler.Context; import org.eclipse.jetty.util.component.AbstractLifeCycle; @@ -60,7 +60,7 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#store(java.lang.String, org.eclipse.jetty.server.session.x.SessionData) + * @see org.eclipse.jetty.server.session.SessionDataStore#store(java.lang.String, org.eclipse.jetty.server.session.SessionData) */ @Override public void store(SessionKey key, SessionData data) throws Exception diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java index 22c22ef5121..c8ed6debc1b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionIdManager.java @@ -23,7 +23,10 @@ import java.util.Random; import javax.servlet.http.HttpServletRequest; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.SessionIdManager; +import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -39,6 +42,8 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme protected String _workerName; protected String _workerAttr; protected long _reseed=100000L; + protected Server _server; + protected SessionScavenger _scavenger; /* ------------------------------------------------------------ */ public AbstractSessionIdManager() @@ -52,10 +57,23 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme } + public void setServer (Server server) + { + _server = server; + } + + public Server getServer () + { + return _server; + } - /* ------------------------------------------------------------ */ - @Override - public abstract void renewSessionId(String oldClusterId, String oldNodeId, HttpServletRequest request); + + public void setSessionScavenger (SessionScavenger scavenger) + { + _scavenger = scavenger; + _scavenger.setSessionIdManager(this); + } + /* ------------------------------------------------------------ */ @@ -212,14 +230,26 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme @Override protected void doStart() throws Exception { + if (_server == null) + throw new IllegalStateException("No Server for SessionIdManager"); initRandom(); _workerAttr=(_workerName!=null && _workerName.startsWith("$"))?_workerName.substring(1):null; + + if (_scavenger == null) + { + LOG.warn("No SessionScavenger set, using defaults"); + _scavenger = new SessionScavenger(); + _scavenger.setSessionIdManager(this); + } + + _scavenger.start(); } /* ------------------------------------------------------------ */ @Override protected void doStop() throws Exception { + _scavenger.stop(); } /* ------------------------------------------------------------ */ @@ -281,5 +311,82 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme return (dot>0)?extendedId.substring(0,dot):extendedId; } + /** + * Remove an id from use by telling all contexts to remove a session with this id. + * + * @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String) + */ + @Override + public void expireAll(String id) + { + //take the id out of the list of known sessionids for this node + removeId(id); + //tell all contexts that may have a session object with this id to + //get rid of them + Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class); + for (int i=0; contexts!=null && i - * 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 specialized version of the Session inner class that provides an attribute Map. - */ -@SuppressWarnings("deprecation") -@ManagedObject("Abstract Session Manager") -public abstract class AbstractSessionManager extends ContainerLifeCycle implements SessionManager -{ - final static Logger __log = SessionHandler.LOG; - - 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; - - static final HttpSessionContext __nullSessionContext=new HttpSessionContext() - { - @Override - public HttpSession getSession(String sessionId) - { - return null; - } - - @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Enumeration getIds() - { - return Collections.enumeration(Collections.EMPTY_LIST); - } - }; - - private boolean _usingCookies=true; - - /* ------------------------------------------------------------ */ - // 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 boolean _secureRequestOnly=true; - - protected final List _sessionAttributeListeners = new CopyOnWriteArrayList(); - protected final List _sessionListeners= new CopyOnWriteArrayList(); - protected final List _sessionIdListeners = new CopyOnWriteArrayList(); - - 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 _usingURLs; - - protected final CounterStatistic _sessionsStats = new CounterStatistic(); - protected final SampleStatistic _sessionTimeStats = new SampleStatistic(); - - - /* ------------------------------------------------------------ */ - public AbstractSessionManager() - { - setSessionTrackingModes(__defaultSessionTrackingModes); - } - - /* ------------------------------------------------------------ */ - public ContextHandler.Context getContext() - { - return _context; - } - - /* ------------------------------------------------------------ */ - public ContextHandler getContextHandler() - { - return _context.getContextHandler(); - } - - @ManagedAttribute("path of the session cookie, or null for default") - public String getSessionPath() - { - return _sessionPath; - } - - @ManagedAttribute("if greater the zero, the time in seconds a session cookie will last for") - public int getMaxCookieAge() - { - return _maxCookieAge; - } - - /* ------------------------------------------------------------ */ - @Override - public HttpCookie access(HttpSession session,boolean secure) - { - long now=System.currentTimeMillis(); - - AbstractSession s = ((SessionIf)session).getSession(); - - if (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; - } - - /* ------------------------------------------------------------ */ - @Override - public void addEventListener(EventListener listener) - { - if (listener instanceof HttpSessionAttributeListener) - _sessionAttributeListeners.add((HttpSessionAttributeListener)listener); - if (listener instanceof HttpSessionListener) - _sessionListeners.add((HttpSessionListener)listener); - if (listener instanceof HttpSessionIdListener) - _sessionIdListeners.add((HttpSessionIdListener)listener); - addBean(listener,false); - } - - /* ------------------------------------------------------------ */ - @Override - public void clearEventListeners() - { - for (EventListener e :getBeans(EventListener.class)) - removeBean(e); - _sessionAttributeListeners.clear(); - _sessionListeners.clear(); - _sessionIdListeners.clear(); - } - - /* ------------------------------------------------------------ */ - @Override - public void complete(HttpSession session) - { - AbstractSession s = ((SessionIf)session).getSession(); - s.complete(); - } - - /* ------------------------------------------------------------ */ - @Override - public void doStart() throws Exception - { - _context=ContextHandler.getCurrentContext(); - _loader=Thread.currentThread().getContextClassLoader(); - - final Server server=getSessionHandler().getServer(); - synchronized (server) - { - if (_sessionIdManager==null) - { - _sessionIdManager=server.getSessionIdManager(); - if (_sessionIdManager==null) - { - //create a default SessionIdManager and set it as the shared - //SessionIdManager for the Server, being careful NOT to use - //the webapp context's classloader, otherwise if the context - //is stopped, the classloader is leaked. - ClassLoader serverLoader = server.getClass().getClassLoader(); - try - { - Thread.currentThread().setContextClassLoader(serverLoader); - _sessionIdManager=new HashSessionIdManager(); - server.setSessionIdManager(_sessionIdManager); - server.manage(_sessionIdManager); - _sessionIdManager.start(); - } - finally - { - Thread.currentThread().setContextClassLoader(_loader); - } - } - - // server session id is never managed by this manager - addBean(_sessionIdManager,false); - } - } - - - // 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(); - - shutdownSessions(); - - _loader=null; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the httpOnly. - */ - @Override - @ManagedAttribute("true if cookies use the http only flag") - public boolean getHttpOnly() - { - return _httpOnly; - } - - /* ------------------------------------------------------------ */ - @Override - public HttpSession getHttpSession(String nodeId) - { - String cluster_id = getSessionIdManager().getId(nodeId); - - AbstractSession session = getSession(cluster_id); - if (session!=null && !session.getNodeId().equals(nodeId)) - session.setIdChanged(true); - return session; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the SessionIdManager used for cross context session management - */ - @Override - @ManagedAttribute("Session ID Manager") - public SessionIdManager getSessionIdManager() - { - return _sessionIdManager; - } - - - /* ------------------------------------------------------------ */ - /** - * @return seconds - */ - @Override - @ManagedAttribute("defailt maximum time a session may be idle for (in s)") - public int getMaxInactiveInterval() - { - return _dftMaxIdleSecs; - } - - /* ------------------------------------------------------------ */ - /** - * @return maximum number of sessions - */ - @ManagedAttribute("maximum number of simultaneous sessions") - public int getSessionsMax() - { - return (int)_sessionsStats.getMax(); - } - - /* ------------------------------------------------------------ */ - /** - * @return total number of sessions - */ - @ManagedAttribute("total number of sessions") - public int getSessionsTotal() - { - return (int)_sessionsStats.getTotal(); - } - - /* ------------------------------------------------------------ */ - @ManagedAttribute("time before a session cookie is re-set (in s)") - public int getRefreshCookieAge() - { - return _refreshCookieAge; - } - - /* ------------------------------------------------------------ */ - /** - * @return same as SessionCookieConfig.getSecure(). If true, session - * cookies are ALWAYS marked as secure. If false, a session cookie is - * ONLY marked as secure if _secureRequestOnly == true and it is a HTTPS request. - */ - @ManagedAttribute("if true, secure cookie flag is set on session cookies") - public boolean getSecureCookies() - { - return _secureCookies; - } - - /* ------------------------------------------------------------ */ - /** - * @return true if session cookie is to be marked as secure only on HTTPS requests - */ - public boolean isSecureRequestOnly() - { - return _secureRequestOnly; - } - - - /* ------------------------------------------------------------ */ - /** - * HTTPS request. Can be overridden by setting SessionCookieConfig.setSecure(true), - * in which case the session cookie will be marked as secure on both HTTPS and HTTP. - * @param secureRequestOnly true to set Session Cookie Config as secure - */ - public void setSecureRequestOnly(boolean secureRequestOnly) - { - _secureRequestOnly = secureRequestOnly; - } - - /* ------------------------------------------------------------ */ - @ManagedAttribute("the set session cookie") - public String getSessionCookie() - { - return _sessionCookie; - } - - /* ------------------------------------------------------------ */ - /** - * A sessioncookie is marked as secure IFF any of the following conditions are true: - *
    - *
  1. SessionCookieConfig.setSecure == true
  2. - *
  3. SessionCookieConfig.setSecure == false && _secureRequestOnly==true && request is HTTPS
  4. - *
- * According to SessionCookieConfig javadoc, case 1 can be used when: - * "... even though the request that initiated the session came over HTTP, - * is to support a topology where the web container is front-ended by an - * SSL offloading load balancer. In this case, the traffic between the client - * and the load balancer will be over HTTPS, whereas the traffic between the - * load balancer and the web container will be over HTTP." - *

- * For case 2, you can use _secureRequestOnly to determine if you want the - * Servlet Spec 3.0 default behavior when SessionCookieConfig.setSecure==false, - * which is: - * - * "they shall be marked as secure only if the request that initiated the - * corresponding session was also secure" - * - *

- * The default for _secureRequestOnly is true, which gives the above behavior. If - * you set it to false, then a session cookie is NEVER marked as secure, even if - * the initiating request was secure. - * - * @see org.eclipse.jetty.server.SessionManager#getSessionCookie(javax.servlet.http.HttpSession, java.lang.String, boolean) - */ - @Override - public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure) - { - if (isUsingCookies()) - { - String sessionPath = (_cookieConfig.getPath()==null) ? contextPath : _cookieConfig.getPath(); - sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath; - String id = getNodeId(session); - HttpCookie cookie = null; - if (_sessionComment == null) - { - cookie = new HttpCookie( - _cookieConfig.getName(), - id, - _cookieConfig.getDomain(), - sessionPath, - _cookieConfig.getMaxAge(), - _cookieConfig.isHttpOnly(), - _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure)); - } - else - { - cookie = new HttpCookie( - _cookieConfig.getName(), - id, - _cookieConfig.getDomain(), - sessionPath, - _cookieConfig.getMaxAge(), - _cookieConfig.isHttpOnly(), - _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure), - _sessionComment, - 1); - } - - return cookie; - } - return null; - } - - @ManagedAttribute("domain of the session cookie, or null for the default") - public String getSessionDomain() - { - return _sessionDomain; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the sessionHandler. - */ - public SessionHandler getSessionHandler() - { - return _sessionHandler; - } - - /* ------------------------------------------------------------ */ - @ManagedAttribute("number of currently active sessions") - public int getSessions() - { - return (int)_sessionsStats.getCurrent(); - } - - /* ------------------------------------------------------------ */ - @Override - @ManagedAttribute("name of use for URL session tracking") - public String getSessionIdPathParameterName() - { - return _sessionIdPathParameterName; - } - - /* ------------------------------------------------------------ */ - @Override - public String getSessionIdPathParameterNamePrefix() - { - return _sessionIdPathParameterNamePrefix; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the usingCookies. - */ - @Override - public boolean isUsingCookies() - { - return _usingCookies; - } - - /* ------------------------------------------------------------ */ - @Override - public boolean isValid(HttpSession session) - { - AbstractSession s = ((SessionIf)session).getSession(); - return s.isValid(); - } - - /* ------------------------------------------------------------ */ - @Override - public String getClusterId(HttpSession session) - { - AbstractSession s = ((SessionIf)session).getSession(); - return s.getClusterId(); - } - - /* ------------------------------------------------------------ */ - @Override - public String getNodeId(HttpSession session) - { - AbstractSession s = ((SessionIf)session).getSession(); - return s.getNodeId(); - } - - /* ------------------------------------------------------------ */ - /** - * Create a new HttpSession for a request - */ - @Override - public HttpSession newHttpSession(HttpServletRequest request) - { - AbstractSession session=newSession(request); - session.setMaxInactiveInterval(_dftMaxIdleSecs); - if (request.isSecure()) - session.setAttribute(AbstractSession.SESSION_CREATED_SECURE, Boolean.TRUE); - addSession(session,true); - return session; - } - - /* ------------------------------------------------------------ */ - @Override - public void removeEventListener(EventListener listener) - { - if (listener instanceof HttpSessionAttributeListener) - _sessionAttributeListeners.remove(listener); - if (listener instanceof HttpSessionListener) - _sessionListeners.remove(listener); - if (listener instanceof HttpSessionIdListener) - _sessionIdListeners.remove(listener); - removeBean(listener); - } - - /* ------------------------------------------------------------ */ - /** - * Reset statistics values - */ - @ManagedOperation(value="reset statistics", impact="ACTION") - 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. - */ - @Override - public void setSessionIdManager(SessionIdManager metaManager) - { - updateBean(_sessionIdManager, metaManager); - _sessionIdManager=metaManager; - } - - /* ------------------------------------------------------------ */ - @Override - public void setMaxInactiveInterval(int seconds) - { - _dftMaxIdleSecs=seconds; - } - - /* ------------------------------------------------------------ */ - public void setRefreshCookieAge(int ageInSeconds) - { - _refreshCookieAge=ageInSeconds; - } - - /* ------------------------------------------------------------ */ - public void setSessionCookie(String cookieName) - { - _sessionCookie=cookieName; - } - - /* ------------------------------------------------------------ */ - /** - * @param sessionHandler - * The sessionHandler to set. - */ - @Override - public void setSessionHandler(SessionHandler sessionHandler) - { - _sessionHandler=sessionHandler; - } - - - /* ------------------------------------------------------------ */ - @Override - public void setSessionIdPathParameterName(String param) - { - _sessionIdPathParameterName =(param==null||"none".equals(param))?null:param; - _sessionIdPathParameterNamePrefix =(param==null||"none".equals(param))?null:(";"+ _sessionIdPathParameterName +"="); - } - /* ------------------------------------------------------------ */ - /** - * @param usingCookies - * The usingCookies to set. - */ - public void setUsingCookies(boolean usingCookies) - { - _usingCookies=usingCookies; - } - - - protected abstract void addSession(AbstractSession session); - - public abstract void invalidateSession(String id); - - - /* ------------------------------------------------------------ */ - /** - * Add the session Registers the session with this manager and registers the - * session ID with the sessionIDManager; - * @param session the session - * @param created true if session was created - */ - protected void addSession(AbstractSession session, boolean created) - { - synchronized (_sessionIdManager) - { - // _sessionIdManager.addSession(session); TODO cope with id coming in from database - addSession(session); - } - - if (created) - { - _sessionsStats.increment(); - if (_sessionListeners!=null) - { - HttpSessionEvent event=new HttpSessionEvent(session); - for (HttpSessionListener listener : _sessionListeners) - listener.sessionCreated(event); - } - } - } - - /* ------------------------------------------------------------ */ - /** - * Get a known existing session - * @param idInCluster The session ID in the cluster, stripped of any worker name. - * @return A Session or null if none exists. - */ - public abstract AbstractSession getSession(String idInCluster); - - /** - * Prepare sessions for session manager shutdown - * - * @throws Exception if unable to shutdown sesssions - */ - protected abstract void shutdownSessions() throws Exception; - - - /* ------------------------------------------------------------ */ - /** - * Create a new session instance - * @param request the request to build the session from - * @return the new session - */ - protected abstract AbstractSession newSession(HttpServletRequest request); - - - /* ------------------------------------------------------------ */ - /** - * @return true if the cluster node id (worker id) is returned as part of the session id by {@link HttpSession#getId()}. Default is false. - */ - public boolean isNodeIdInSessionId() - { - return _nodeIdInSessionId; - } - - /* ------------------------------------------------------------ */ - /** - * @param nodeIdInSessionId true if the cluster node id (worker id) will be returned as part of the session id by {@link HttpSession#getId()}. Default is false. - */ - public void setNodeIdInSessionId(boolean nodeIdInSessionId) - { - _nodeIdInSessionId=nodeIdInSessionId; - } - - /* ------------------------------------------------------------ */ - /** Remove session from manager - * @param session The session to remove - * @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and - * {@link SessionIdManager#expireAll(String)} should be called. - */ - public void removeSession(HttpSession session, boolean invalidate) - { - AbstractSession s = ((SessionIf)session).getSession(); - removeSession(s,invalidate); - } - - /* ------------------------------------------------------------ */ - /** - * Remove session from manager - * @param session The session to remove - * @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and - * {@link SessionIdManager#expireAll(String)} should be called. - * @return if the session was removed - */ - public boolean removeSession(AbstractSession session, boolean invalidate) - { - // Remove session from context and global maps - boolean removed = removeSession(session.getClusterId()); - - if (removed) - { - _sessionsStats.decrement(); - _sessionTimeStats.set(round((System.currentTimeMillis() - session.getCreationTime())/1000.0)); - - // Remove session from all context and global id maps - _sessionIdManager.removeId(session.getId()); - if (invalidate) - _sessionIdManager.expireAll(session.getClusterId()); - - if (invalidate && _sessionListeners!=null) - { - HttpSessionEvent event=new HttpSessionEvent(session); - for (int i = _sessionListeners.size()-1; i>=0; i--) - { - _sessionListeners.get(i).sessionDestroyed(event); - } - } - } - - return removed; - } - - /* ------------------------------------------------------------ */ - protected abstract boolean removeSession(String idInCluster); - - /* ------------------------------------------------------------ */ - /** - * @return maximum amount of time session remained valid - */ - @ManagedAttribute("maximum amount of time sessions have remained active (in s)") - public long getSessionTimeMax() - { - return _sessionTimeStats.getMax(); - } - - /* ------------------------------------------------------------ */ - @Override - public Set getDefaultSessionTrackingModes() - { - return __defaultSessionTrackingModes; - } - - /* ------------------------------------------------------------ */ - @Override - 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 isUsingURLs() - { - return _usingURLs; - } - - /* ------------------------------------------------------------ */ - @Override - public SessionCookieConfig getSessionCookieConfig() - { - return _cookieConfig; - } - - /* ------------------------------------------------------------ */ - private SessionCookieConfig _cookieConfig = - new CookieConfig(); - - - /* ------------------------------------------------------------ */ - /** - * @return total amount of time all sessions remained valid - */ - @ManagedAttribute("total time sessions have remained valid") - public long getSessionTimeTotal() - { - return _sessionTimeStats.getTotal(); - } - - /* ------------------------------------------------------------ */ - /** - * @return mean amount of time session remained valid - */ - @ManagedAttribute("mean time sessions remain valid (in s)") - public double getSessionTimeMean() - { - return _sessionTimeStats.getMean(); - } - - /* ------------------------------------------------------------ */ - /** - * @return standard deviation of amount of time session remained valid - */ - @ManagedAttribute("standard deviation a session remained valid (in s)") - public double getSessionTimeStdDev() - { - return _sessionTimeStats.getStdDev(); - } - - /* ------------------------------------------------------------ */ - /** - * @see org.eclipse.jetty.server.SessionManager#isCheckingRemoteSessionIdEncoding() - */ - @Override - @ManagedAttribute("check remote session id encoding") - public boolean isCheckingRemoteSessionIdEncoding() - { - return _checkingRemoteSessionIdEncoding; - } - - /* ------------------------------------------------------------ */ - /** - * @see org.eclipse.jetty.server.SessionManager#setCheckingRemoteSessionIdEncoding(boolean) - */ - @Override - public void setCheckingRemoteSessionIdEncoding(boolean remote) - { - _checkingRemoteSessionIdEncoding=remote; - } - - - /* ------------------------------------------------------------ */ - /** - * Tell the HttpSessionIdListeners the id changed. - * NOTE: this method must be called LAST in subclass overrides, after the session has been updated - * with the new id. - * @see org.eclipse.jetty.server.SessionManager#renewSessionId(java.lang.String, java.lang.String, java.lang.String, java.lang.String) - */ - @Override - public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId) - { - if (!_sessionIdListeners.isEmpty()) - { - AbstractSession session = getSession(newClusterId); - HttpSessionEvent event = new HttpSessionEvent(session); - for (HttpSessionIdListener l:_sessionIdListeners) - { - l.sessionIdChanged(event, oldClusterId); - } - } - - } - - /** - * CookieConfig - * - * Implementation of the javax.servlet.SessionCookieConfig. - */ - public final class CookieConfig implements 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) - { - if (_context != null && _context.getContextHandler().isAvailable()) - throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); - _sessionComment = comment; - } - - @Override - public void setDomain(String domain) - { - if (_context != null && _context.getContextHandler().isAvailable()) - throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); - _sessionDomain=domain; - } - - @Override - public void setHttpOnly(boolean httpOnly) - { - if (_context != null && _context.getContextHandler().isAvailable()) - throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); - _httpOnly=httpOnly; - } - - @Override - public void setMaxAge(int maxAge) - { - if (_context != null && _context.getContextHandler().isAvailable()) - throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); - _maxCookieAge=maxAge; - } - - @Override - public void setName(String name) - { - if (_context != null && _context.getContextHandler().isAvailable()) - throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); - _sessionCookie=name; - } - - @Override - public void setPath(String path) - { - if (_context != null && _context.getContextHandler().isAvailable()) - throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); - _sessionPath=path; - } - - @Override - public void setSecure(boolean secure) - { - if (_context != null && _context.getContextHandler().isAvailable()) - throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started"); - _secureCookies=secure; - } - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /** - * Interface that any session wrapper should implement so that - * SessionManager may access the Jetty session implementation. - * - */ - public interface SessionIf extends HttpSession - { - public AbstractSession getSession(); - } - - public void doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value) - { - if (!_sessionAttributeListeners.isEmpty()) - { - HttpSessionBindingEvent event=new HttpSessionBindingEvent(session,name,old==null?value:old); - - for (HttpSessionAttributeListener l : _sessionAttributeListeners) - { - if (old==null) - l.attributeAdded(event); - else if (value==null) - l.attributeRemoved(event); - else - l.attributeReplaced(event); - } - } - } -} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionStore.java similarity index 92% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionStore.java index 4f309a14e09..0a3ad38e15b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionStore.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.util.Collections; import java.util.Map; @@ -123,7 +123,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements * the data for it from a SessionDataStore associated with the * session manager. * - * @see org.eclipse.jetty.server.session.x.SessionStore#get(java.lang.String) + * @see org.eclipse.jetty.server.session.SessionStore#get(java.lang.String) */ @Override public Session get(SessionKey key) throws Exception @@ -147,7 +147,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements * If the session manager supports a session data store, write the * session data through to the session data store. * - * @see org.eclipse.jetty.server.session.x.SessionStore#put(java.lang.String, org.eclipse.jetty.server.session.x.Session) + * @see org.eclipse.jetty.server.session.SessionStore#put(java.lang.String, org.eclipse.jetty.server.session.Session) */ @Override public void put(SessionKey key, Session session) throws Exception @@ -187,7 +187,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements * * TODO should this check through to the backing store? * - * @see org.eclipse.jetty.server.session.x.SessionStore#exists(java.lang.String) + * @see org.eclipse.jetty.server.session.SessionStore#exists(java.lang.String) */ @Override public boolean exists(SessionKey key) @@ -199,7 +199,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements /** * Remove a session object from this store and from any backing store. * - * @see org.eclipse.jetty.server.session.x.SessionStore#delete(java.lang.String) + * @see org.eclipse.jetty.server.session.SessionStore#delete(java.lang.String) */ @Override public boolean delete(SessionKey key) throws Exception @@ -221,7 +221,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements /** - * @see org.eclipse.jetty.server.session.x.SessionStore#getExpired() + * @see org.eclipse.jetty.server.session.SessionStore#getExpired() */ @Override public Set getExpired() diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AlwaysStaleStrategy.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AlwaysStaleStrategy.java similarity index 86% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AlwaysStaleStrategy.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/AlwaysStaleStrategy.java index 90eeb0fb28d..264ea6495cd 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AlwaysStaleStrategy.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AlwaysStaleStrategy.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; /** * AlwaysStale @@ -28,7 +28,7 @@ public class AlwaysStaleStrategy implements StalenessStrategy { /** - * @see org.eclipse.jetty.server.session.x.StalenessStrategy#isStale(org.eclipse.jetty.server.session.x.Session) + * @see org.eclipse.jetty.server.session.StalenessStrategy#isStale(org.eclipse.jetty.server.session.Session) */ @Override public boolean isStale(Session session) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/DatabaseAdaptor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/DatabaseAdaptor.java similarity index 99% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/DatabaseAdaptor.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/DatabaseAdaptor.java index ba73fad3481..4c2cb7ca416 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/DatabaseAdaptor.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/DatabaseAdaptor.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.io.ByteArrayInputStream; import java.io.InputStream; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/FileSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/FileSessionDataStore.java similarity index 92% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/FileSessionDataStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/FileSessionDataStore.java index 8b4fbc067f3..01e17250c09 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/FileSessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/FileSessionDataStore.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -87,7 +87,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore } /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.x.SessionKey, long, long, long, long) + * @see org.eclipse.jetty.server.session.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.SessionKey, long, long, long, long) */ @Override public SessionData newSessionData(SessionKey key, long created, long accessed, long lastAccessed, long maxInactiveMs) @@ -96,7 +96,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore } /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#delete(org.eclipse.jetty.server.session.x.SessionKey) + * @see org.eclipse.jetty.server.session.SessionDataStore#delete(org.eclipse.jetty.server.session.SessionKey) */ @Override public boolean delete(SessionKey key) throws Exception @@ -116,7 +116,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore } /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#getExpired() + * @see org.eclipse.jetty.server.session.SessionDataStore#getExpired() */ @Override public Set getExpired(Set candidates) @@ -127,7 +127,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#load(org.eclipse.jetty.server.session.x.SessionKey) + * @see org.eclipse.jetty.server.session.SessionDataStore#load(org.eclipse.jetty.server.session.SessionKey) */ @Override public SessionData load(SessionKey key) throws Exception @@ -226,7 +226,7 @@ public class FileSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionDataStore#doStore(org.eclipse.jetty.server.session.x.SessionKey, org.eclipse.jetty.server.session.x.SessionData) + * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(org.eclipse.jetty.server.session.SessionKey, org.eclipse.jetty.server.session.SessionData) */ @Override public void doStore(SessionKey key, SessionData data) throws Exception diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java index dbeef474c5d..d5d117742ef 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java @@ -16,166 +16,64 @@ // ======================================================================== // + package org.eclipse.jetty.server.session; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Random; import java.util.Set; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.eclipse.jetty.server.Handler; -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.ConcurrentHashSet; -/* ------------------------------------------------------------ */ /** - * HashSessionIdManager. An in-memory implementation of the session ID manager. + * HashSessionIdManager + * + * */ public class HashSessionIdManager extends AbstractSessionIdManager { private final Set _ids = new ConcurrentHashSet(); - - private Server _server; - /* ------------------------------------------------------------ */ - public HashSessionIdManager() - { - } - - /* ------------------------------------------------------------ */ - public HashSessionIdManager(Random random) - { - super(random); - } - - - public void setServer (Server server) - { - _server = server; - } - - /* ------------------------------------------------------------ */ - /** - * @return Collection of String session IDs - */ - public Collection getSessions() - { - return Collections.unmodifiableCollection(_ids); - } - - - - /* ------------------------------------------------------------ */ - @Override - protected void doStart() throws Exception - { - if (_server == null) - throw new IllegalStateException ("No server set on HashSessionIdManager"); - super.doStart(); - } - - /* ------------------------------------------------------------ */ - @Override - protected void doStop() throws Exception - { - _ids.clear(); - super.doStop(); - } - - /* ------------------------------------------------------------ */ - /** - * @see SessionIdManager#isIdInUse(String) + /** + * @see org.eclipse.jetty.server.SessionIdManager#isIdInUse(java.lang.String) */ @Override public boolean isIdInUse(String id) - { - return _ids.contains(id); + { + return _ids.contains(id); } - /* ------------------------------------------------------------ */ - /** - * @see SessionIdManager#addSession(HttpSession) + + /** + * @see org.eclipse.jetty.server.session.AbstractSessionIdManager#newSessionId(long) + */ + @Override + public String newSessionId(long seedTerm) + { + String id = super.newSessionId(seedTerm); + useId(id); + return id; + } + + + /** + * @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String) */ @Override public void useId(String id) { - _ids.add(id); + if (id == null) + return; + + _ids.add(id); } + /** + * @see org.eclipse.jetty.server.SessionIdManager#removeId(java.lang.String) + */ @Override public void removeId(String id) { - _ids.remove(id); - } - - - /* ------------------------------------------------------------ */ - /** - * @see SessionIdManager#expireAll(String) - */ - @Override - public void expireAll(String id) - { - //take the id out of the list of known sessionids for this node - removeId(id); - - synchronized (_ids) - { - //tell all contexts that may have a session object with this id to - //get rid of them - Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class); - for (int i=0; contexts!=null && i - * This manager supports saving sessions to disk, either periodically or at shutdown. - * Sessions can also have their content idle saved to disk to reduce the memory overheads of large idle sessions. - *

- * This manager will create it's own Timer instance to scavenge threads, unless it discovers a shared Timer instance - * set as the "org.eclipse.jetty.server.session.timer" attribute of the ContextHandler. + * * */ -public class HashSessionManager extends AbstractSessionManager +public class HashSessionManager extends SessionManager { - final static Logger LOG = SessionHandler.LOG; - - protected final ConcurrentMap _sessions=new ConcurrentHashMap(); - private Scheduler _timer; - private Scheduler.Task _task; - long _scavengePeriodMs=30000; - long _savePeriodMs=0; //don't do period saves by default - long _idleSavePeriodMs = 0; // don't idle save sessions by default. - private Scheduler.Task _saveTask; - File _storeDir; - private boolean _lazyLoad=false; - private volatile boolean _sessionsLoaded=false; - private boolean _deleteUnrestorableSessions=false; + protected FileSessionDataStore _sessionDataStore = new FileSessionDataStore(); - /** - * Scavenger - * - */ - protected class Scavenger implements Runnable - { - @Override - public void run() - { - try - { - scavenge(); - } - finally - { - if (_timer != null && _timer.isRunning()) { - _task = _timer.schedule(this, _scavengePeriodMs, TimeUnit.MILLISECONDS); - } - } - } - } - - /** - * Saver - * - */ - protected class Saver implements Runnable - { - @Override - public void run() - { - try - { - saveSessions(true); - } - catch (Exception e) - { - LOG.warn(e); - } - finally - { - if (_timer != null && _timer.isRunning()) - _saveTask = _timer.schedule(this, _savePeriodMs, TimeUnit.MILLISECONDS); - } - } - } - - - /* ------------------------------------------------------------ */ - public HashSessionManager() - { - super(); - } - - /* ------------------------------------------------------------ */ - /** - * @see AbstractSessionManager#doStart() - */ @Override public void doStart() throws Exception { - //try shared scheduler from Server first - _timer = getSessionHandler().getServer().getBean(Scheduler.class); - if (_timer == null) - { - //try one passed into the context - ServletContext context = ContextHandler.getCurrentContext(); - if (context!=null) - _timer = (Scheduler)context.getAttribute("org.eclipse.jetty.server.session.timer"); - } - - if (_timer == null) - { - //make a scheduler if none useable - _timer=new ScheduledExecutorScheduler(toString()+"Timer",true); - addBean(_timer,true); - } - else - addBean(_timer,false); + _sessionStore = new MemorySessionStore(); + ((AbstractSessionStore)_sessionStore).setSessionDataStore(_sessionDataStore); super.doStart(); - - setScavengePeriod(getScavengePeriod()); - - if (_storeDir!=null) - { - if (!_storeDir.exists()) - _storeDir.mkdirs(); - - if (!_lazyLoad) - restoreSessions(); - } - - setSavePeriod(getSavePeriod()); } - /* ------------------------------------------------------------ */ - /** - * @see AbstractSessionManager#doStop() - */ @Override public void doStop() throws Exception { - // stop the scavengers - synchronized(this) - { - if (_saveTask!=null) - _saveTask.cancel(); - - _saveTask=null; - if (_task!=null) - _task.cancel(); - - _task=null; - _timer=null; - } - - - // This will callback invalidate sessions - where we decide if we will save super.doStop(); - - _sessions.clear(); - - } - - /* ------------------------------------------------------------ */ - /** - * @return the period in seconds at which a check is made for sessions to be invalidated. - */ - public int getScavengePeriod() - { - return (int)(_scavengePeriodMs/1000); - } - - - /* ------------------------------------------------------------ */ - @Override - public int getSessions() - { - int sessions=super.getSessions(); - if (LOG.isDebugEnabled()) - { - if (_sessions.size()!=sessions) - LOG.warn("sessions: "+_sessions.size()+"!="+sessions); - } - return sessions; - } - - /* ------------------------------------------------------------ */ - /** - * @return seconds Idle period after which a session is saved - */ - public int getIdleSavePeriod() - { - if (_idleSavePeriodMs <= 0) - return 0; - - return (int)(_idleSavePeriodMs / 1000); - } - - /* ------------------------------------------------------------ */ - /** - * Configures the period in seconds after which a session is deemed idle and saved - * to save on session memory. - * - * The session is persisted, the values attribute map is cleared and the session set to idled. - * - * @param seconds Idle period after which a session is saved - */ - public void setIdleSavePeriod(int seconds) - { - _idleSavePeriodMs = seconds * 1000L; - } - - /* ------------------------------------------------------------ */ - @Override - public void setMaxInactiveInterval(int seconds) - { - super.setMaxInactiveInterval(seconds); - if (_dftMaxIdleSecs>0&&_scavengePeriodMs>_dftMaxIdleSecs*1000L) - setScavengePeriod((_dftMaxIdleSecs+9)/10); - } - - /* ------------------------------------------------------------ */ - /** - * @param seconds the period is seconds at which sessions are periodically saved to disk - */ - public void setSavePeriod (int seconds) - { - long period = (seconds * 1000L); - if (period < 0) - period=0; - _savePeriodMs=period; - - if (_timer!=null) - { - synchronized (this) - { - if (_saveTask!=null) - _saveTask.cancel(); - _saveTask = null; - if (_savePeriodMs > 0 && _storeDir!=null) //only save if we have a directory configured - { - _saveTask = _timer.schedule(new Saver(),_savePeriodMs,TimeUnit.MILLISECONDS); - } - } - } - } - - /* ------------------------------------------------------------ */ - /** - * @return the period in seconds at which sessions are periodically saved to disk - */ - public int getSavePeriod () - { - if (_savePeriodMs<=0) - return 0; - - return (int)(_savePeriodMs/1000); - } - - /* ------------------------------------------------------------ */ - /** - * @param seconds the period in seconds at which a check is made for sessions to be invalidated. - */ - public void setScavengePeriod(int seconds) - { - if (seconds==0) - seconds=60; - - long old_period=_scavengePeriodMs; - long period=seconds*1000L; - if (period>60000) - period=60000; - if (period<1000) - period=1000; - - _scavengePeriodMs=period; - - synchronized (this) - { - if (_timer!=null && (period!=old_period || _task==null)) - { - if (_task!=null) - { - _task.cancel(); - _task = null; - } - - _task = _timer.schedule(new Scavenger(),_scavengePeriodMs, TimeUnit.MILLISECONDS); - } - } - } - - /* -------------------------------------------------------------- */ - /** - * Find sessions that have timed out and invalidate them. This runs in the - * SessionScavenger thread. - */ - protected void scavenge() - { - //don't attempt to scavenge if we are shutting down - if (isStopping() || isStopped()) - return; - - Thread thread=Thread.currentThread(); - ClassLoader old_loader=thread.getContextClassLoader(); - try - { - if (_loader!=null) - thread.setContextClassLoader(_loader); - - // For each session - long now=System.currentTimeMillis(); - __log.debug("Scavenging sessions at {}", now); - - for (Iterator i=_sessions.values().iterator(); i.hasNext();) - { - HashedSession session=i.next(); - long idleTime=session.getMaxInactiveInterval()*1000L; - if (idleTime>0&&session.getAccessed()+idleTime 0 && session.getAccessed()+_idleSavePeriodMs < now) - { - try - { - session.idle(); - } - catch (Exception e) - { - __log.warn("Problem idling session "+ session.getId(), e); - } - } - } - } - finally - { - thread.setContextClassLoader(old_loader); - } - } - - /* ------------------------------------------------------------ */ - @Override - protected void addSession(AbstractSession session) - { - if (isRunning()) - _sessions.put(session.getClusterId(),(HashedSession)session); - } - - /* ------------------------------------------------------------ */ - @Override - public AbstractSession getSession(String idInCluster) - { - if ( _lazyLoad && !_sessionsLoaded) - { - try - { - restoreSessions(); - } - catch(Exception e) - { - LOG.warn(e); - } - } - - Map sessions=_sessions; - if (sessions==null) - return null; - - HashedSession session = sessions.get(idInCluster); - - if (session == null && _lazyLoad) - session=restoreSession(idInCluster); - if (session == null) - return null; - - if (_idleSavePeriodMs!=0) - session.deIdle(); - - return session; - } - - /* ------------------------------------------------------------ */ - @Override - protected void shutdownSessions() throws Exception - { - // Invalidate all sessions to cause unbind events - ArrayList sessions=new ArrayList(_sessions.values()); - int loop=100; - while (sessions.size()>0 && loop-->0) - { - // If we are called from doStop - if (isStopping() && _storeDir != null && _storeDir.exists() && _storeDir.canWrite()) - { - // Then we only save and remove the session from memory- it is not invalidated. - for (HashedSession session : sessions) - { - session.save(false); - _sessions.remove(session.getClusterId()); - } - } - else - { - for (HashedSession session : sessions) - session.invalidate(); - } - - // check that no new sessions were created while we were iterating - sessions=new ArrayList(_sessions.values()); - } } - - - /* ------------------------------------------------------------ */ /** - * @see org.eclipse.jetty.server.SessionManager#renewSessionId(java.lang.String, java.lang.String, java.lang.String, java.lang.String) + * Get the SessionDataStore to configure it + * @return */ - @Override - public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId) + public FileSessionDataStore getSessionDataStore() { - try - { - Map sessions=_sessions; - if (sessions == null) - return; - - HashedSession session = sessions.remove(oldClusterId); - if (session == null) - return; - - session.remove(); //delete any previously saved session - session.setClusterId(newClusterId); //update ids - session.setNodeId(newNodeId); - session.save(); //save updated session: TODO consider only saving file if idled - sessions.put(newClusterId, session); - - super.renewSessionId(oldClusterId, oldNodeId, newClusterId, newNodeId); - } - catch (Exception e) - { - LOG.warn(e); - } - } - - - - - @Override - public void invalidateSession(String id) - { - // TODO Auto-generated method stub - //Called from SessionIdManager when invalidating all sessions with the same id - //across contexts + return _sessionDataStore; } - /* ------------------------------------------------------------ */ - @Override - protected AbstractSession newSession(HttpServletRequest request) - { - return new HashedSession(this, request); - } - - /* ------------------------------------------------------------ */ - protected AbstractSession newSession(long created, long accessed, String clusterId) - { - return new HashedSession(this, created,accessed, clusterId); - } - - /* ------------------------------------------------------------ */ - @Override - protected boolean removeSession(String clusterId) - { - return _sessions.remove(clusterId)!=null; - } - - /* ------------------------------------------------------------ */ - public void setStoreDirectory (File dir) throws IOException - { - // CanonicalFile is used to capture the base store directory in a way that will - // work on Windows. Case differences may through off later checks using this directory. - _storeDir=dir.getCanonicalFile(); - } - - /* ------------------------------------------------------------ */ - public File getStoreDirectory () - { - return _storeDir; - } - - /* ------------------------------------------------------------ */ - public void setLazyLoad(boolean lazyLoad) - { - _lazyLoad = lazyLoad; - } - - /* ------------------------------------------------------------ */ - public boolean isLazyLoad() - { - return _lazyLoad; - } - - /* ------------------------------------------------------------ */ - public boolean isDeleteUnrestorableSessions() - { - return _deleteUnrestorableSessions; - } - - /* ------------------------------------------------------------ */ - public void setDeleteUnrestorableSessions(boolean deleteUnrestorableSessions) - { - _deleteUnrestorableSessions = deleteUnrestorableSessions; - } - - /* ------------------------------------------------------------ */ - public void restoreSessions () throws Exception - { - _sessionsLoaded = true; - - if (_storeDir==null || !_storeDir.exists()) - { - return; - } - - if (!_storeDir.canRead()) - { - LOG.warn ("Unable to restore Sessions: Cannot read from Session storage directory "+_storeDir.getAbsolutePath()); - return; - } - - String[] files = _storeDir.list(); - for (int i=0;files!=null&&i0) - { - // input stream should not be closed here - ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is); - for (int i=0; i0&&(getMaxInactiveInterval()*1000L/10)<_hashSessionManager._scavengePeriodMs) - _hashSessionManager.setScavengePeriod((secs+9)/10); - } - - /* ------------------------------------------------------------ */ - @Override - protected void doInvalidate() - throws IllegalStateException - { - super.doInvalidate(); - remove(); - } - - - /* ------------------------------------------------------------ */ - /** - * Remove from the disk - */ - synchronized void remove () - { - if (_hashSessionManager._storeDir!=null && getId()!=null) - { - String id=getId(); - File f = new File(_hashSessionManager._storeDir, id); - f.delete(); - } - } - - /* ------------------------------------------------------------ */ - synchronized void save(boolean reactivate) - throws Exception - { - // Only idle the session if not already idled and no previous save/idle has failed - if (!isIdled() && !_saveFailed) - { - if (LOG.isDebugEnabled()) - LOG.debug("Saving {} {}",super.getId(),reactivate); - - try - { - willPassivate(); - save(); - if (reactivate) - didActivate(); - else - clearAttributes(); - } - catch (Exception e) - { - LOG.warn("Problem saving session " + super.getId(), e); - _idled=false; // assume problem was before _values.clear(); - } - } - } - - - - synchronized void save () - throws Exception - { - File file = null; - if (!_saveFailed && _hashSessionManager._storeDir != null) - { - file = new File(_hashSessionManager._storeDir, super.getId()); - if (file.exists()) - { - file.delete(); - } - - try(FileOutputStream fos = new FileOutputStream(file,false)) - { - save(fos); - } - catch (Exception e) - { - saveFailed(); // We won't try again for this session - if (file != null) - file.delete(); // No point keeping the file if we didn't save the whole session - throw e; - } - } - } - - - /* ------------------------------------------------------------ */ - public synchronized void save(OutputStream os) throws IOException - { - DataOutputStream out = new DataOutputStream(os); - out.writeUTF(getClusterId()); - out.writeUTF(getNodeId()); - out.writeLong(getCreationTime()); - out.writeLong(getAccessed()); - - /* Don't write these out, as they don't make sense to store because they - * either they cannot be true or their value will be restored in the - * Session constructor. - */ - //out.writeBoolean(_invalid); - //out.writeBoolean(_doInvalidate); - //out.writeBoolean( _newSession); - out.writeInt(getRequests()); - out.writeInt(getAttributes()); - ObjectOutputStream oos = new ObjectOutputStream(out); - Enumeration e=getAttributeNames(); - while(e.hasMoreElements()) - { - String key=e.nextElement(); - oos.writeUTF(key); - oos.writeObject(doGet(key)); - } - - out.writeInt(getMaxInactiveInterval()); - } - - /* ------------------------------------------------------------ */ - public synchronized void deIdle() - { - if (isIdled() && !_deIdleFailed) - { - // Access now to prevent race with idling period - access(System.currentTimeMillis()); - - if (LOG.isDebugEnabled()) - LOG.debug("De-idling " + super.getId()); - - FileInputStream fis = null; - - try - { - File file = new File(_hashSessionManager._storeDir, super.getId()); - if (!file.exists() || !file.canRead()) - throw new FileNotFoundException(file.getName()); - - fis = new FileInputStream(file); - _idled = false; - _hashSessionManager.restoreSession(fis, this); - IO.close(fis); - - didActivate(); - - // If we are doing period saves, then there is no point deleting at this point - if (_hashSessionManager._savePeriodMs == 0) - file.delete(); - } - catch (Exception e) - { - deIdleFailed(); - LOG.warn("Problem de-idling session " + super.getId(), e); - if (fis != null) IO.close(fis);//Must ensure closed before invalidate - invalidate(); - } - } - } - - - /* ------------------------------------------------------------ */ - /** - * Idle the session to reduce session memory footprint. - * - * The session is idled by persisting it, then clearing the session values attribute map and finally setting - * it to an idled state. - * @throws Exception if unable to save session - */ - public synchronized void idle() - throws Exception - { - save(false); - _idled = true; - } - - /* ------------------------------------------------------------ */ - public synchronized boolean isIdled() - { - return _idled; - } - - /* ------------------------------------------------------------ */ - public synchronized boolean isSaveFailed() - { - return _saveFailed; - } - - /* ------------------------------------------------------------ */ - public synchronized void saveFailed() - { - _saveFailed = true; - } - - /* ------------------------------------------------------------ */ - public synchronized void deIdleFailed() - { - _deIdleFailed = true; - } - - /* ------------------------------------------------------------ */ - public synchronized boolean isDeIdleFailed() - { - return _deIdleFailed; - } -} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java similarity index 98% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionDataStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java index 25d23c29144..f52bd05c8ed 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -522,7 +522,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.x.SessionKey, long, long, long, long) + * @see org.eclipse.jetty.server.session.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.SessionKey, long, long, long, long) */ @Override public SessionData newSessionData(SessionKey key, long created, long accessed, long lastAccessed, long maxInactiveMs) @@ -576,7 +576,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#load(org.eclipse.jetty.server.session.x.SessionKey) + * @see org.eclipse.jetty.server.session.SessionDataStore#load(org.eclipse.jetty.server.session.SessionKey) */ @Override public SessionData load(SessionKey key) throws Exception @@ -645,7 +645,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#delete(java.lang.String) + * @see org.eclipse.jetty.server.session.SessionDataStore#delete(java.lang.String) */ @Override public boolean delete(SessionKey key) throws Exception @@ -665,7 +665,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionDataStore#doStore() + * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore() */ @Override public void doStore(SessionKey key, SessionData data) throws Exception @@ -776,7 +776,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#getExpired() + * @see org.eclipse.jetty.server.session.SessionDataStore#getExpired() */ @Override public Set getExpired(Set candidates) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java index 933336bea5a..23b007f9183 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java @@ -44,6 +44,7 @@ import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.SessionManager; import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; import org.eclipse.jetty.util.thread.Scheduler; @@ -57,334 +58,19 @@ import org.eclipse.jetty.util.thread.Scheduler; * to support distributed sessions. * */ -public class JDBCSessionIdManager extends AbstractSessionIdManager +public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.AbstractSessionIdManager { - final static Logger LOG = SessionHandler.LOG; + private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session"); + public final static int MAX_INTERVAL_NOT_SET = -999; protected final HashSet _sessionIds = new HashSet(); protected Server _server; - protected Driver _driver; - protected String _driverClassName; - protected String _connectionUrl; - protected DataSource _datasource; - protected String _jndiName; + protected SessionScavenger _scavenger; - protected int _deleteBlockSize = 10; //number of ids to include in where 'in' clause + private DatabaseAdaptor _dbAdaptor = new DatabaseAdaptor(); - protected Scheduler.Task _task; //scavenge task - protected Scheduler _scheduler; - protected Scavenger _scavenger; - protected boolean _ownScheduler; - protected long _lastScavengeTime; - protected long _scavengeIntervalMs = 1000L * 60 * 10; //10mins - - - protected String _createSessionIdTable; - protected String _createSessionTable; - - protected String _selectBoundedExpiredSessions; - private String _selectExpiredSessions; - - protected String _insertId; - protected String _deleteId; - protected String _queryId; - - protected String _insertSession; - protected String _deleteSession; - protected String _updateSession; - protected String _updateSessionNode; - protected String _updateSessionAccessTime; - - protected DatabaseAdaptor _dbAdaptor = new DatabaseAdaptor(); protected SessionIdTableSchema _sessionIdTableSchema = new SessionIdTableSchema(); - protected SessionTableSchema _sessionTableSchema = new SessionTableSchema(); - - - - - /** - * SessionTableSchema - * - */ - public static class SessionTableSchema - { - protected DatabaseAdaptor _dbAdaptor; - protected String _tableName = "JettySessions"; - protected String _rowIdColumn = "rowId"; - protected String _idColumn = "sessionId"; - protected String _contextPathColumn = "contextPath"; - protected String _virtualHostColumn = "virtualHost"; - protected String _lastNodeColumn = "lastNode"; - protected String _accessTimeColumn = "accessTime"; - protected String _lastAccessTimeColumn = "lastAccessTime"; - protected String _createTimeColumn = "createTime"; - protected String _cookieTimeColumn = "cookieTime"; - protected String _lastSavedTimeColumn = "lastSavedTime"; - protected String _expiryTimeColumn = "expiryTime"; - protected String _maxIntervalColumn = "maxInterval"; - protected String _mapColumn = "map"; - - - protected void setDatabaseAdaptor(DatabaseAdaptor dbadaptor) - { - _dbAdaptor = dbadaptor; - } - - - public String getTableName() - { - return _tableName; - } - public void setTableName(String tableName) - { - checkNotNull(tableName); - _tableName = tableName; - } - public String getRowIdColumn() - { - if ("rowId".equals(_rowIdColumn) && _dbAdaptor.isRowIdReserved()) - _rowIdColumn = "srowId"; - return _rowIdColumn; - } - public void setRowIdColumn(String rowIdColumn) - { - checkNotNull(rowIdColumn); - if (_dbAdaptor == null) - throw new IllegalStateException ("DbAdaptor is null"); - - if (_dbAdaptor.isRowIdReserved() && "rowId".equals(rowIdColumn)) - throw new IllegalArgumentException("rowId is reserved word for Oracle"); - - _rowIdColumn = rowIdColumn; - } - public String getIdColumn() - { - return _idColumn; - } - public void setIdColumn(String idColumn) - { - checkNotNull(idColumn); - _idColumn = idColumn; - } - public String getContextPathColumn() - { - return _contextPathColumn; - } - public void setContextPathColumn(String contextPathColumn) - { - checkNotNull(contextPathColumn); - _contextPathColumn = contextPathColumn; - } - public String getVirtualHostColumn() - { - return _virtualHostColumn; - } - public void setVirtualHostColumn(String virtualHostColumn) - { - checkNotNull(virtualHostColumn); - _virtualHostColumn = virtualHostColumn; - } - public String getLastNodeColumn() - { - return _lastNodeColumn; - } - public void setLastNodeColumn(String lastNodeColumn) - { - checkNotNull(lastNodeColumn); - _lastNodeColumn = lastNodeColumn; - } - public String getAccessTimeColumn() - { - return _accessTimeColumn; - } - public void setAccessTimeColumn(String accessTimeColumn) - { - checkNotNull(accessTimeColumn); - _accessTimeColumn = accessTimeColumn; - } - public String getLastAccessTimeColumn() - { - return _lastAccessTimeColumn; - } - public void setLastAccessTimeColumn(String lastAccessTimeColumn) - { - checkNotNull(lastAccessTimeColumn); - _lastAccessTimeColumn = lastAccessTimeColumn; - } - public String getCreateTimeColumn() - { - return _createTimeColumn; - } - public void setCreateTimeColumn(String createTimeColumn) - { - checkNotNull(createTimeColumn); - _createTimeColumn = createTimeColumn; - } - public String getCookieTimeColumn() - { - return _cookieTimeColumn; - } - public void setCookieTimeColumn(String cookieTimeColumn) - { - checkNotNull(cookieTimeColumn); - _cookieTimeColumn = cookieTimeColumn; - } - public String getLastSavedTimeColumn() - { - return _lastSavedTimeColumn; - } - public void setLastSavedTimeColumn(String lastSavedTimeColumn) - { - checkNotNull(lastSavedTimeColumn); - _lastSavedTimeColumn = lastSavedTimeColumn; - } - public String getExpiryTimeColumn() - { - return _expiryTimeColumn; - } - public void setExpiryTimeColumn(String expiryTimeColumn) - { - checkNotNull(expiryTimeColumn); - _expiryTimeColumn = expiryTimeColumn; - } - public String getMaxIntervalColumn() - { - return _maxIntervalColumn; - } - public void setMaxIntervalColumn(String maxIntervalColumn) - { - checkNotNull(maxIntervalColumn); - _maxIntervalColumn = maxIntervalColumn; - } - public String getMapColumn() - { - return _mapColumn; - } - public void setMapColumn(String mapColumn) - { - checkNotNull(mapColumn); - _mapColumn = mapColumn; - } - - public String getCreateStatementAsString () - { - if (_dbAdaptor == null) - throw new IllegalStateException ("No DBAdaptor"); - - String blobType = _dbAdaptor.getBlobType(); - String longType = _dbAdaptor.getLongType(); - - return "create table "+_tableName+" ("+getRowIdColumn()+" varchar(120), "+_idColumn+" varchar(120), "+ - _contextPathColumn+" varchar(60), "+_virtualHostColumn+" varchar(60), "+_lastNodeColumn+" varchar(60), "+_accessTimeColumn+" "+longType+", "+ - _lastAccessTimeColumn+" "+longType+", "+_createTimeColumn+" "+longType+", "+_cookieTimeColumn+" "+longType+", "+ - _lastSavedTimeColumn+" "+longType+", "+_expiryTimeColumn+" "+longType+", "+_maxIntervalColumn+" "+longType+", "+ - _mapColumn+" "+blobType+", primary key("+getRowIdColumn()+"))"; - } - - public String getCreateIndexOverExpiryStatementAsString (String indexName) - { - return "create index "+indexName+" on "+getTableName()+" ("+getExpiryTimeColumn()+")"; - } - - public String getCreateIndexOverSessionStatementAsString (String indexName) - { - return "create index "+indexName+" on "+getTableName()+" ("+getIdColumn()+", "+getContextPathColumn()+")"; - } - - public String getAlterTableForMaxIntervalAsString () - { - if (_dbAdaptor == null) - throw new IllegalStateException ("No DBAdaptor"); - String longType = _dbAdaptor.getLongType(); - String stem = "alter table "+getTableName()+" add "+getMaxIntervalColumn()+" "+longType; - if (_dbAdaptor.getDBName().contains("oracle")) - return stem + " default "+ MAX_INTERVAL_NOT_SET + " not null"; - else - return stem +" not null default "+ MAX_INTERVAL_NOT_SET; - } - - private void checkNotNull(String s) - { - if (s == null) - throw new IllegalArgumentException(s); - } - public String getInsertSessionStatementAsString() - { - return "insert into "+getTableName()+ - " ("+getRowIdColumn()+", "+getIdColumn()+", "+getContextPathColumn()+", "+getVirtualHostColumn()+", "+getLastNodeColumn()+ - ", "+getAccessTimeColumn()+", "+getLastAccessTimeColumn()+", "+getCreateTimeColumn()+", "+getCookieTimeColumn()+ - ", "+getLastSavedTimeColumn()+", "+getExpiryTimeColumn()+", "+getMaxIntervalColumn()+", "+getMapColumn()+") "+ - " values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - } - public String getDeleteSessionStatementAsString() - { - return "delete from "+getTableName()+ - " where "+getRowIdColumn()+" = ?"; - } - public String getUpdateSessionStatementAsString() - { - return "update "+getTableName()+ - " set "+getIdColumn()+" = ?, "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+ - getLastAccessTimeColumn()+" = ?, "+getLastSavedTimeColumn()+" = ?, "+getExpiryTimeColumn()+" = ?, "+ - getMaxIntervalColumn()+" = ?, "+getMapColumn()+" = ? where "+getRowIdColumn()+" = ?"; - } - public String getUpdateSessionNodeStatementAsString() - { - return "update "+getTableName()+ - " set "+getLastNodeColumn()+" = ? where "+getRowIdColumn()+" = ?"; - } - public String getUpdateSessionAccessTimeStatementAsString() - { - return "update "+getTableName()+ - " set "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+getLastAccessTimeColumn()+" = ?, "+ - getLastSavedTimeColumn()+" = ?, "+getExpiryTimeColumn()+" = ?, "+getMaxIntervalColumn()+" = ? where "+getRowIdColumn()+" = ?"; - } - - public String getBoundedExpiredSessionsStatementAsString() - { - return "select * from "+getTableName()+" where "+getLastNodeColumn()+" = ? and "+getExpiryTimeColumn()+" >= ? and "+getExpiryTimeColumn()+" <= ?"; - } - - public String getSelectExpiredSessionsStatementAsString() - { - return "select * from "+getTableName()+" where "+getExpiryTimeColumn()+" >0 and "+getExpiryTimeColumn()+" <= ?"; - } - - public PreparedStatement getLoadStatement (Connection connection, String rowId, String contextPath, String virtualHosts) - throws SQLException - { - if (_dbAdaptor == null) - throw new IllegalStateException("No DB adaptor"); - - - if (contextPath == null || "".equals(contextPath)) - { - if (_dbAdaptor.isEmptyStringNull()) - { - PreparedStatement statement = connection.prepareStatement("select * from "+getTableName()+ - " where "+getIdColumn()+" = ? and "+ - getContextPathColumn()+" is null and "+ - getVirtualHostColumn()+" = ?"); - statement.setString(1, rowId); - statement.setString(2, virtualHosts); - - return statement; - } - } - - PreparedStatement statement = connection.prepareStatement("select * from "+getTableName()+ - " where "+getIdColumn()+" = ? and "+getContextPathColumn()+ - " = ? and "+getVirtualHostColumn()+" = ?"); - statement.setString(1, rowId); - statement.setString(2, contextPath); - statement.setString(3, virtualHosts); - - return statement; - } - } - - /** * SessionIdTableSchema @@ -392,14 +78,10 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager */ public static class SessionIdTableSchema { - protected DatabaseAdaptor _dbAdaptor; protected String _tableName = "JettySessionIds"; protected String _idColumn = "id"; - - public void setDatabaseAdaptor(DatabaseAdaptor dbAdaptor) - { - _dbAdaptor = dbAdaptor; - } + protected DatabaseAdaptor _jdbc; + public String getIdColumn() { return _idColumn; @@ -442,178 +124,40 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager return "create table "+_tableName+" ("+_idColumn+" varchar(120), primary key("+_idColumn+"))"; } + protected void prepareTables (DatabaseAdaptor jdbc) + throws Exception + { + _jdbc = jdbc; + try (Connection connection = _jdbc.getConnection(); + Statement statement = connection.createStatement()) + { + //make the id table + connection.setAutoCommit(true); + DatabaseMetaData metaData = connection.getMetaData(); + _jdbc.adaptTo(metaData); + + + //checking for table existence is case-sensitive, but table creation is not + String tableName = _jdbc.convertIdentifier(getTableName()); + try (ResultSet result = metaData.getTables(null, null, tableName, null)) + { + if (!result.next()) + { + //table does not exist, so create it + statement.executeUpdate(getCreateStatementAsString()); + } + } + } + } + private void checkNotNull(String s) { if (s == null) throw new IllegalArgumentException(s); } } - - - /** - * DatabaseAdaptor - * - * Handles differences between databases. - * - * Postgres uses the getBytes and setBinaryStream methods to access - * a "bytea" datatype, which can be up to 1Gb of binary data. MySQL - * is happy to use the "blob" type and getBlob() methods instead. - * - * TODO if the differences become more major it would be worthwhile - * refactoring this class. - */ - public static class DatabaseAdaptor - { - String _dbName; - boolean _isLower; - boolean _isUpper; - - protected String _blobType; //if not set, is deduced from the type of the database at runtime - protected String _longType; //if not set, is deduced from the type of the database at runtime - - - public DatabaseAdaptor () - { - } - - - public void adaptTo(DatabaseMetaData dbMeta) - throws SQLException - { - _dbName = dbMeta.getDatabaseProductName().toLowerCase(Locale.ENGLISH); - if (LOG.isDebugEnabled()) - LOG.debug ("Using database {}",_dbName); - _isLower = dbMeta.storesLowerCaseIdentifiers(); - _isUpper = dbMeta.storesUpperCaseIdentifiers(); - } - - - public void setBlobType(String blobType) - { - _blobType = blobType; - } - - public String getBlobType () - { - if (_blobType != null) - return _blobType; - - if (_dbName.startsWith("postgres")) - return "bytea"; - - return "blob"; - } - - - public void setLongType(String longType) - { - _longType = longType; - } - - - public String getLongType () - { - if (_longType != null) - return _longType; - - if (_dbName == null) - throw new IllegalStateException ("DbAdaptor missing metadata"); - - if (_dbName.startsWith("oracle")) - return "number(20)"; - - return "bigint"; - } - - - /** - * Convert a camel case identifier into either upper or lower - * depending on the way the db stores identifiers. - * - * @param identifier the raw identifier - * @return the converted identifier - */ - public String convertIdentifier (String identifier) - { - if (_dbName == null) - throw new IllegalStateException ("DbAdaptor missing metadata"); - - if (_isLower) - return identifier.toLowerCase(Locale.ENGLISH); - if (_isUpper) - return identifier.toUpperCase(Locale.ENGLISH); - - return identifier; - } - - public String getDBName () - { - return _dbName; - } - - - public InputStream getBlobInputStream (ResultSet result, String columnName) - throws SQLException - { - if (_dbName == null) - throw new IllegalStateException ("DbAdaptor missing metadata"); - - if (_dbName.startsWith("postgres")) - { - byte[] bytes = result.getBytes(columnName); - return new ByteArrayInputStream(bytes); - } - - Blob blob = result.getBlob(columnName); - return blob.getBinaryStream(); - } - - - public boolean isEmptyStringNull () - { - if (_dbName == null) - throw new IllegalStateException ("DbAdaptor missing metadata"); - - return (_dbName.startsWith("oracle")); - } - - /** - * rowId is a reserved word for Oracle, so change the name of this column - * @return true if db in use is oracle - */ - public boolean isRowIdReserved () - { - if (_dbName == null) - throw new IllegalStateException ("DbAdaptor missing metadata"); - - return (_dbName != null && _dbName.startsWith("oracle")); - } - } - - - /** - * Scavenger - * - */ - protected class Scavenger implements Runnable - { - - @Override - public void run() - { - try - { - scavenge(); - } - finally - { - if (_scheduler != null && _scheduler.isRunning()) - _task = _scheduler.schedule(this, _scavengeIntervalMs, TimeUnit.MILLISECONDS); - } - } - } - - + + public JDBCSessionIdManager(Server server) { super(); @@ -626,188 +170,11 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager _server=server; } - /** - * Configure jdbc connection information via a jdbc Driver - * - * @param driverClassName the driver classname - * @param connectionUrl the driver connection url - */ - public void setDriverInfo (String driverClassName, String connectionUrl) - { - _driverClassName=driverClassName; - _connectionUrl=connectionUrl; - } - - /** - * Configure jdbc connection information via a jdbc Driver - * - * @param driverClass the driver class - * @param connectionUrl the driver connection url - */ - public void setDriverInfo (Driver driverClass, String connectionUrl) - { - _driver=driverClass; - _connectionUrl=connectionUrl; - } - - - public void setDatasource (DataSource ds) - { - _datasource = ds; - } - - public DataSource getDataSource () - { - return _datasource; - } - - public String getDriverClassName() - { - return _driverClassName; - } - - public String getConnectionUrl () - { - return _connectionUrl; - } - - public void setDatasourceName (String jndi) - { - _jndiName=jndi; - } - - public String getDatasourceName () - { - return _jndiName; - } - - /** - * @param name the name of the blob - * @deprecated see DbAdaptor.setBlobType - */ - @Deprecated - public void setBlobType (String name) - { - _dbAdaptor.setBlobType(name); - } - - public DatabaseAdaptor getDbAdaptor() - { - return _dbAdaptor; - } - - public void setDbAdaptor(DatabaseAdaptor dbAdaptor) - { - if (dbAdaptor == null) - throw new IllegalStateException ("DbAdaptor cannot be null"); - - _dbAdaptor = dbAdaptor; - } - - /** - * @return the blob type - * @deprecated see DbAdaptor.getBlobType - */ - @Deprecated - public String getBlobType () - { - return _dbAdaptor.getBlobType(); - } - - /** - * @return the long type - * @deprecated see DbAdaptor.getLogType - */ - @Deprecated - public String getLongType() - { - return _dbAdaptor.getLongType(); - } - - /** - * @param longType the long type - * @deprecated see DbAdaptor.setLongType - */ - @Deprecated - public void setLongType(String longType) - { - _dbAdaptor.setLongType(longType); - } - public SessionIdTableSchema getSessionIdTableSchema() { return _sessionIdTableSchema; } - public void setSessionIdTableSchema(SessionIdTableSchema sessionIdTableSchema) - { - if (sessionIdTableSchema == null) - throw new IllegalArgumentException("Null SessionIdTableSchema"); - - _sessionIdTableSchema = sessionIdTableSchema; - } - - public SessionTableSchema getSessionTableSchema() - { - return _sessionTableSchema; - } - - public void setSessionTableSchema(SessionTableSchema sessionTableSchema) - { - _sessionTableSchema = sessionTableSchema; - } - - public void setDeleteBlockSize (int bsize) - { - this._deleteBlockSize = bsize; - } - - public int getDeleteBlockSize () - { - return this._deleteBlockSize; - } - - public void setScavengeInterval (long sec) - { - if (sec<=0) - sec=60; - - long old_period=_scavengeIntervalMs; - long period=sec*1000L; - - _scavengeIntervalMs=period; - - //add a bit of variability into the scavenge time so that not all - //nodes with the same scavenge time sync up - long tenPercent = _scavengeIntervalMs/10; - if ((System.currentTimeMillis()%2) == 0) - _scavengeIntervalMs += tenPercent; - - if (LOG.isDebugEnabled()) - LOG.debug("Scavenging every "+_scavengeIntervalMs+" ms"); - - synchronized (this) - { - //if (_timer!=null && (period!=old_period || _task==null)) - if (_scheduler != null && (period!=old_period || _task==null)) - { - if (_task!=null) - _task.cancel(); - if (_scavenger == null) - _scavenger = new Scavenger(); - _task = _scheduler.schedule(_scavenger,_scavengeIntervalMs,TimeUnit.MILLISECONDS); - } - } - } - - public long getScavengeInterval () - { - return _scavengeIntervalMs/1000; - } - - - - @Override public String newSessionId(long seedTerm) { @@ -817,7 +184,12 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager } - //TODO useId might not be the right paradigm + + /** + * Record the session id as being in use + * + * @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String) + */ public void useId (String id) { if (id == null) @@ -841,6 +213,10 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager /** + * Remove the id from in-use set + * + * Prevents another context from using this id + * * @see org.eclipse.jetty.server.SessionIdManager#removeId(java.lang.String) */ @Override @@ -867,6 +243,76 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager } + /** + * Insert a new used session id into the table. + * + * @param id + * @throws SQLException + */ + private void insert (String id) + throws SQLException + { + try (Connection connection = _dbAdaptor.getConnection(); + PreparedStatement query = connection.prepareStatement(_sessionIdTableSchema.getSelectStatementAsString())) + { + connection.setAutoCommit(true); + query.setString(1, id); + try (ResultSet result = query.executeQuery()) + { + //only insert the id if it isn't in the db already + if (!result.next()) + { + try (PreparedStatement statement = connection.prepareStatement(_sessionIdTableSchema.getInsertStatementAsString())) + { + statement.setString(1, id); + statement.executeUpdate(); + } + } + } + } + } + + /** + * Remove a session id from the table. + * + * @param id + * @throws SQLException + */ + private void delete (String id) + throws SQLException + { + try (Connection connection = _dbAdaptor.getConnection(); + PreparedStatement statement = connection.prepareStatement(_sessionIdTableSchema.getDeleteStatementAsString())) + { + connection.setAutoCommit(true); + statement.setString(1, id); + statement.executeUpdate(); + } + } + + + /** + * Check if a session id exists. + * + * @param id + * @return + * @throws SQLException + */ + private boolean exists (String id) + throws SQLException + { + try (Connection connection = _dbAdaptor.getConnection(); + PreparedStatement statement = connection.prepareStatement(_sessionIdTableSchema.getSelectStatementAsString())) + { + connection.setAutoCommit(true); + statement.setString(1, id); + try (ResultSet result = statement.executeQuery()) + { + return result.next(); + } + } + } + @Override public boolean isIdInUse(String id) @@ -896,6 +342,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager return false; } } + /** * Invalidate the session matching the id on all contexts. @@ -904,61 +351,36 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager */ @Override public void expireAll(String id) - { - //take the id out of the list of known sessionids for this node - removeId(id); - + { synchronized (_sessionIds) { - //tell all contexts that may have a session object with this id to - //get rid of them - Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class); - for (int i=0; contexts!=null && i 0) - { - connection = getConnection(); - connection.setAutoCommit(true); - Set expiredSessionIds = new HashSet(); - - - //Pass 1: find sessions for which we were last managing node that have just expired since last pass - long lowerBound = (_lastScavengeTime - _scavengeIntervalMs); - long upperBound = _lastScavengeTime; - if (LOG.isDebugEnabled()) - LOG.debug (getWorkerName()+"- Pass 1: Searching for sessions expired between "+lowerBound + " and "+upperBound); - - try (PreparedStatement statement = connection.prepareStatement(_selectBoundedExpiredSessions)) - { - statement.setString(1, getWorkerName()); - statement.setLong(2, lowerBound); - statement.setLong(3, upperBound); - try (ResultSet result = statement.executeQuery()) - { - while (result.next()) - { - String sessionId = result.getString(_sessionTableSchema.getIdColumn()); - expiredSessionIds.add(sessionId); - if (LOG.isDebugEnabled()) LOG.debug ("Found expired sessionId="+sessionId); - } - } - } - scavengeSessions(expiredSessionIds, false); - - - //Pass 2: find sessions that have expired a while ago for which this node was their last manager - try (PreparedStatement selectExpiredSessions = connection.prepareStatement(_selectExpiredSessions)) - { - expiredSessionIds.clear(); - upperBound = _lastScavengeTime - (2 * _scavengeIntervalMs); - if (upperBound > 0) - { - if (LOG.isDebugEnabled()) LOG.debug(getWorkerName()+"- Pass 2: Searching for sessions expired before "+upperBound); - selectExpiredSessions.setLong(1, upperBound); - try (ResultSet result = selectExpiredSessions.executeQuery()) - { - while (result.next()) - { - String sessionId = result.getString(_sessionTableSchema.getIdColumn()); - String lastNode = result.getString(_sessionTableSchema.getLastNodeColumn()); - if ((getWorkerName() == null && lastNode == null) || (getWorkerName() != null && getWorkerName().equals(lastNode))) - expiredSessionIds.add(sessionId); - if (LOG.isDebugEnabled()) LOG.debug ("Found expired sessionId="+sessionId+" last managed by "+getWorkerName()); - } - } - scavengeSessions(expiredSessionIds, false); - } - - - //Pass 3: - //find all sessions that have expired at least a couple of scanIntervals ago - //if we did not succeed in loading them (eg their related context no longer exists, can't be loaded etc) then - //they are simply deleted - upperBound = _lastScavengeTime - (3 * _scavengeIntervalMs); - expiredSessionIds.clear(); - if (upperBound > 0) - { - if (LOG.isDebugEnabled()) LOG.debug(getWorkerName()+"- Pass 3: searching for sessions expired before "+upperBound); - selectExpiredSessions.setLong(1, upperBound); - try (ResultSet result = selectExpiredSessions.executeQuery()) - { - while (result.next()) - { - String sessionId = result.getString(_sessionTableSchema.getIdColumn()); - expiredSessionIds.add(sessionId); - if (LOG.isDebugEnabled()) LOG.debug ("Found expired sessionId="+sessionId); - } - } - scavengeSessions(expiredSessionIds, true); - } - } - } - } - catch (Exception e) - { - if (isRunning()) - LOG.warn("Problem selecting expired sessions", e); - else - LOG.ignore(e); - } - finally - { - _lastScavengeTime=System.currentTimeMillis(); - if (LOG.isDebugEnabled()) LOG.debug(getWorkerName()+"- Scavenge sweep ended at "+_lastScavengeTime); - if (connection != null) - { - try - { - connection.close(); - } - catch (SQLException e) - { - LOG.warn(e); - } - } - } - } - - - /** - * @param expiredSessionIds - */ - private void scavengeSessions (Set expiredSessionIds, boolean forceDelete) - { - Set remainingIds = new HashSet(expiredSessionIds); - Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class); - for (int i=0; contexts!=null && i successfullyExpiredIds = ((JDBCSessionManager)manager).expire(expiredSessionIds); - if (successfullyExpiredIds != null) - remainingIds.removeAll(successfullyExpiredIds); - } - } - } - - //Any remaining ids are of those sessions that no context removed - if (!remainingIds.isEmpty() && forceDelete) - { - LOG.info("Forcibly deleting unrecoverable expired sessions {}", remainingIds); - try - { - //ensure they aren't in the local list of in-use session ids - synchronized (_sessionIds) - { - _sessionIds.removeAll(remainingIds); - } - - cleanExpiredSessionIds(remainingIds); - } - catch (Exception e) - { - LOG.warn("Error removing expired session ids", e); - } - } - } - - - - - private void cleanExpiredSessionIds (Set expiredIds) - throws Exception - { - if (expiredIds == null || expiredIds.isEmpty()) - return; - - String[] ids = expiredIds.toArray(new String[expiredIds.size()]); - try (Connection con = getConnection()) - { - con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); - con.setAutoCommit(false); - - int start = 0; - int end = 0; - int blocksize = _deleteBlockSize; - int block = 0; - - try (Statement statement = con.createStatement()) - { - while (end < ids.length) - { - start = block*blocksize; - if ((ids.length - start) >= blocksize) - end = start + blocksize; - else - end = ids.length; - - //take them out of the sessionIds table - statement.executeUpdate(fillInClause("delete from "+_sessionIdTableSchema.getTableName()+" where "+_sessionIdTableSchema.getIdColumn()+" in ", ids, start, end)); - //take them out of the sessions table - statement.executeUpdate(fillInClause("delete from "+_sessionTableSchema.getTableName()+" where "+_sessionTableSchema.getIdColumn()+" in ", ids, start, end)); - block++; - } - } - catch (Exception e) - { - con.rollback(); - throw e; - } - con.commit(); - } - } - /** @@ -1455,33 +433,6 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager buff.append(")"); return buff.toString(); } - - - - private void initializeDatabase () - throws Exception - { - if (_datasource != null) - return; //already set up - - if (_jndiName!=null) - { - InitialContext ic = new InitialContext(); - _datasource = (DataSource)ic.lookup(_jndiName); - } - else if ( _driver != null && _connectionUrl != null ) - { - DriverManager.registerDriver(_driver); - } - else if (_driverClassName != null && _connectionUrl != null) - { - Class.forName(_driverClassName); - } - else - throw new IllegalStateException("No database configured for sessions"); - } - - - + } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java index 313aaca61a5..15c80d95260 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java @@ -19,1168 +19,51 @@ package org.eclipse.jetty.server.session; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.ObjectOutputStream; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSessionEvent; -import javax.servlet.http.HttpSessionListener; - -import org.eclipse.jetty.server.SessionIdManager; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.session.JDBCSessionIdManager.SessionTableSchema; -import org.eclipse.jetty.util.ClassLoadingObjectInputStream; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - /** - * JDBCSessionManager. - *

- * SessionManager that persists sessions to a database to enable clustering. - *

- * Session data is persisted to the JettySessions table: - *

- *
rowId
(unique in cluster: webapp name/path + virtualhost + sessionId)
- *
contextPath
(of the context owning the session)
- *
sessionId
(unique in a context)
- *
lastNode
(name of node last handled session)
- *
accessTime
(time in milliseconds session was accessed)
- *
lastAccessTime
(previous time in milliseconds session was accessed)
- *
createTime
(time in milliseconds session created)
- *
cookieTime
(time in milliseconds session cookie created)
- *
lastSavedTime
(last time in milliseconds session access times were saved)
- *
expiryTime
(time in milliseconds that the session is due to expire)
- *
map
(attribute map)
- *
+ * JDBCSessionManager + * * - * As an optimization, to prevent thrashing the database, we do not persist - * the accessTime and lastAccessTime every time the session is accessed. Rather, - * we write it out every so often. The frequency is controlled by the saveIntervalSec - * field. */ -public class JDBCSessionManager extends AbstractSessionManager +public class JDBCSessionManager extends SessionManager { - private static final Logger LOG = Log.getLogger(JDBCSessionManager.class); - - private ConcurrentHashMap _sessions; - protected JDBCSessionIdManager _jdbcSessionIdMgr = null; - protected long _saveIntervalSec = 60; //only persist changes to session access times every 60 secs - protected SessionTableSchema _sessionTableSchema; - + protected DatabaseAdaptor _db = new DatabaseAdaptor(); + protected JDBCSessionDataStore _sessionDataStore = new JDBCSessionDataStore(); - /** - * Session - * - * Session instance. - */ - public class Session extends MemSession - { - private static final long serialVersionUID = 5208464051134226143L; - - /** - * If dirty, session needs to be (re)persisted - */ - protected boolean _dirty=false; - - - - - - /** - * Time in msec since the epoch that the session will expire - */ - protected long _expiryTime; - - - /** - * Time in msec since the epoch that the session was last persisted - */ - protected long _lastSaved; - - - /** - * Unique identifier of the last node to host the session - */ - protected String _lastNode; - - - /** - * Virtual host for context (used to help distinguish 2 sessions with same id on different contexts) - */ - protected String _virtualHost; - - - /** - * Unique row in db for session - */ - protected String _rowId; - - - /** - * Mangled context name (used to help distinguish 2 sessions with same id on different contexts) - */ - protected String _canonicalContext; - - - /** - * Session from a request. - * - * @param request the request - */ - protected Session (HttpServletRequest request) - { - super(JDBCSessionManager.this,request); - int maxInterval=getMaxInactiveInterval(); - _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L)); - _virtualHost = JDBCSessionManager.getVirtualHost(_context); - _canonicalContext = canonicalize(_context.getContextPath()); - _lastNode = getSessionIdManager().getWorkerName(); - } - - - /** - * Session restored from database - * @param sessionId the session id - * @param rowId the row id - * @param created the created timestamp - * @param accessed the access timestamp - * @param maxInterval the max inactive interval (in seconds) - */ - protected Session (String sessionId, String rowId, long created, long accessed, long maxInterval) - { - super(JDBCSessionManager.this, created, accessed, sessionId); - _rowId = rowId; - super.setMaxInactiveInterval((int)maxInterval); //restore the session's previous inactivity interval setting - _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L)); - } - - - protected synchronized String getRowId() - { - return _rowId; - } - - protected synchronized void setRowId(String rowId) - { - _rowId = rowId; - } - - public synchronized void setVirtualHost (String vhost) - { - _virtualHost=vhost; - } - - public synchronized String getVirtualHost () - { - return _virtualHost; - } - - public synchronized long getLastSaved () - { - return _lastSaved; - } - - public synchronized void setLastSaved (long time) - { - _lastSaved=time; - } - - public synchronized void setExpiryTime (long time) - { - _expiryTime=time; - } - - public synchronized long getExpiryTime () - { - return _expiryTime; - } - - - public synchronized void setCanonicalContext(String str) - { - _canonicalContext=str; - } - - public synchronized String getCanonicalContext () - { - return _canonicalContext; - } - - - public synchronized void setLastNode (String node) - { - _lastNode=node; - } - - public synchronized String getLastNode () - { - return _lastNode; - } - - @Override - public void setAttribute (String name, Object value) - { - Object old = changeAttribute(name, value); - if (value == null && old == null) - return; //if same as remove attribute but attribute was already removed, no change - - _dirty = true; - } - - @Override - public void removeAttribute (String name) - { - Object old = changeAttribute(name, null); - if (old != null) //only dirty if there was a previous value - _dirty=true; - } - - - /** - * Entry to session. - * Called by SessionHandler on inbound request and the session already exists in this node's memory. - * - * @see org.eclipse.jetty.server.session.AbstractSession#access(long) - */ - @Override - protected boolean access(long time) - { - synchronized (this) - { - if (super.access(time)) - { - int maxInterval=getMaxInactiveInterval(); - _expiryTime = (maxInterval <= 0 ? 0 : (time + maxInterval*1000L)); - return true; - } - return false; - } - } - - - - - - /** - * Change the max idle time for this session. This recalculates the expiry time. - * @see org.eclipse.jetty.server.session.AbstractSession#setMaxInactiveInterval(int) - */ - @Override - public void setMaxInactiveInterval(int secs) - { - synchronized (this) - { - super.setMaxInactiveInterval(secs); - int maxInterval=getMaxInactiveInterval(); - _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L)); - //force the session to be written out right now - try - { - updateSessionAccessTime(this); - } - catch (Exception e) - { - LOG.warn("Problem saving changed max idle time for session "+ this, e); - } - } - } - - - /** - * Exit from session - * @see org.eclipse.jetty.server.session.AbstractSession#complete() - */ - @Override - protected void complete() - { - synchronized (this) - { - super.complete(); - try - { - if (isValid()) - { - if (_dirty) - { - //The session attributes have changed, write to the db, ensuring - //http passivation/activation listeners called - save(true); - } - else if ((getAccessed() - _lastSaved) >= (getSaveInterval() * 1000L)) - { - updateSessionAccessTime(this); - } - } - } - catch (Exception e) - { - LOG.warn("Problem persisting changed session data id="+getId(), e); - } - finally - { - _dirty=false; - } - } - } - - protected void save() throws Exception - { - synchronized (this) - { - try - { - updateSession(this); - } - finally - { - _dirty = false; - } - } - } - - protected void save (boolean reactivate) throws Exception - { - synchronized (this) - { - if (_dirty) - { - //The session attributes have changed, write to the db, ensuring - //http passivation/activation listeners called - willPassivate(); - updateSession(this); - if (reactivate) - didActivate(); - } - } - } - - - @Override - protected void timeout() throws IllegalStateException - { - if (LOG.isDebugEnabled()) - LOG.debug("Timing out session id="+getClusterId()); - super.timeout(); - } - - - @Override - public String toString () - { - return "Session rowId="+_rowId+",id="+getId()+",lastNode="+_lastNode+ - ",created="+getCreationTime()+",accessed="+getAccessed()+ - ",lastAccessed="+getLastAccessedTime()+",cookieSet="+getCookieSetTime()+ - ",maxInterval="+getMaxInactiveInterval()+",lastSaved="+_lastSaved+",expiry="+_expiryTime; - } - } - - - - - /** - * Set the time in seconds which is the interval between - * saving the session access time to the database. - * - * This is an optimization that prevents the database from - * being overloaded when a session is accessed very frequently. - * - * On session exit, if the session attributes have NOT changed, - * the time at which we last saved the accessed - * time is compared to the current accessed time. If the interval - * is at least saveIntervalSecs, then the access time will be - * persisted to the database. - * - * If any session attribute does change, then the attributes and - * the accessed time are persisted. - * - * @param sec the save interval in seconds - */ - public void setSaveInterval (long sec) - { - _saveIntervalSec=sec; - } - - public long getSaveInterval () - { - return _saveIntervalSec; - } - - - - /** - * A method that can be implemented in subclasses to support - * distributed caching of sessions. This method will be - * called whenever the session is written to the database - * because the session data has changed. - * - * This could be used eg with a JMS backplane to notify nodes - * that the session has changed and to delete the session from - * the node's cache, and re-read it from the database. - * @param session the session to invalidate - */ - public void cacheInvalidate (Session session) - { - - } - - - /** - * A session has been requested by its id on this node. - * - * Load the session by id AND context path from the database. - * Multiple contexts may share the same session id (due to dispatching) - * but they CANNOT share the same contents. - * - * Check if last node id is my node id, if so, then the session we have - * in memory cannot be stale. If another node used the session last, then - * we need to refresh from the db. - * - * NOTE: this method will go to the database, so if you only want to check - * for the existence of a Session in memory, use _sessions.get(id) instead. - * - * @see org.eclipse.jetty.server.session.AbstractSessionManager#getSession(java.lang.String) - */ - @Override - public Session getSession(String idInCluster) - { - Session session = null; - - synchronized (this) - { - Session memSession = (Session)_sessions.get(idInCluster); - - //check if we need to reload the session - - //as an optimization, don't reload on every access - //to reduce the load on the database. This introduces a window of - //possibility that the node may decide that the session is local to it, - //when the session has actually been live on another node, and then - //re-migrated to this node. This should be an extremely rare occurrence, - //as load-balancers are generally well-behaved and consistently send - //sessions to the same node, changing only iff that node fails. - //Session data = null; - long now = System.currentTimeMillis(); - if (LOG.isDebugEnabled()) - { - if (memSession==null) - LOG.debug("getSession("+idInCluster+"): not in session map,"+ - " now="+now+ - " lastSaved="+(memSession==null?0:memSession._lastSaved)+ - " interval="+(_saveIntervalSec * 1000L)); - else - LOG.debug("getSession("+idInCluster+"): in session map, "+ - " hashcode="+memSession.hashCode()+ - " now="+now+ - " lastSaved="+(memSession==null?0:memSession._lastSaved)+ - " interval="+(_saveIntervalSec * 1000L)+ - " lastNode="+memSession._lastNode+ - " thisNode="+getSessionIdManager().getWorkerName()+ - " difference="+(now - memSession._lastSaved)); - } - - try - { - if (memSession==null) - { - if (LOG.isDebugEnabled()) - LOG.debug("getSession("+idInCluster+"): no session in session map. Reloading session data from db."); - session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context)); - } - else if ((now - memSession._lastSaved) >= (_saveIntervalSec * 1000L)) - { - if (LOG.isDebugEnabled()) - LOG.debug("getSession("+idInCluster+"): stale session. Reloading session data from db."); - session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context)); - } - else - { - if (LOG.isDebugEnabled()) - LOG.debug("getSession("+idInCluster+"): session in session map"); - session = memSession; - } - } - catch (Exception e) - { - LOG.warn("Unable to load session "+idInCluster, e); - return null; - } - - - //If we have a session - if (session != null) - { - //If the session was last used on a different node, or session doesn't exist on this node - if (!session.getLastNode().equals(getSessionIdManager().getWorkerName()) || memSession==null) - { - //if session doesn't expire, or has not already expired, update it and put it in this nodes' memory - if (session._expiryTime <= 0 || session._expiryTime > now) - { - if (LOG.isDebugEnabled()) - LOG.debug("getSession("+idInCluster+"): lastNode="+session.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName()); - - session.setLastNode(getSessionIdManager().getWorkerName()); - _sessions.put(idInCluster, session); - - //update in db - try - { - updateSessionNode(session); - session.didActivate(); - } - catch (Exception e) - { - LOG.warn("Unable to update freshly loaded session "+idInCluster, e); - return null; - } - } - else - { - if (LOG.isDebugEnabled()) - LOG.debug("getSession ({}): Session has expired", idInCluster); - //ensure that the session id for the expired session is deleted so that a new session with the - //same id cannot be created (because the idInUse() test would succeed) - _jdbcSessionIdMgr.removeId(idInCluster); - session=null; - } - - } - else - { - //the session loaded from the db and the one in memory are the same, so keep using the one in memory - session = memSession; - if (LOG.isDebugEnabled()) - LOG.debug("getSession({}): Session not stale {}", idInCluster,session); - } - } - else - { - //No session in db with matching id and context path. - LOG.debug("getSession({}): No session in database matching id={}",idInCluster,idInCluster); - } - - return session; - } - } - - - /** - * Get the number of sessions. - * - * @see org.eclipse.jetty.server.session.AbstractSessionManager#getSessions() - */ - @Override - public int getSessions() - { - return _sessions.size(); - } - - - /** - * Start the session manager. - * - * @see org.eclipse.jetty.server.session.AbstractSessionManager#doStart() - */ @Override public void doStart() throws Exception { - if (_sessionIdManager==null) - throw new IllegalStateException("No session id manager defined"); - - _jdbcSessionIdMgr = (JDBCSessionIdManager)_sessionIdManager; - _sessionTableSchema = _jdbcSessionIdMgr.getSessionTableSchema(); - - _sessions = new ConcurrentHashMap(); - + _sessionStore = new MemorySessionStore(); + _sessionDataStore.setDatabaseAdaptor(_db); + ((AbstractSessionStore)_sessionStore).setSessionDataStore(_sessionDataStore); + super.doStart(); } - - /** - * Stop the session manager. - * - * @see org.eclipse.jetty.server.session.AbstractSessionManager#doStop() - */ @Override public void doStop() throws Exception { super.doStop(); - _sessions.clear(); - _sessions = null; - } - - @Override - protected void shutdownSessions() - { - //Save the current state of all of our sessions, - //do NOT delete them (so other nodes can manage them) - long gracefulStopMs = getContextHandler().getServer().getStopTimeout(); - long stopTime = 0; - if (gracefulStopMs > 0) - stopTime = System.nanoTime() + (TimeUnit.NANOSECONDS.convert(gracefulStopMs, TimeUnit.MILLISECONDS)); - - ArrayList sessions = (_sessions == null? new ArrayList() :new ArrayList(_sessions.values()) ); - - // loop while there are sessions, and while there is stop time remaining, or if no stop time, just 1 loop - while (sessions.size() > 0 && ((stopTime > 0 && (System.nanoTime() < stopTime)) || (stopTime == 0))) - { - for (Session session : sessions) - { - try - { - session.save(false); - } - catch (Exception e) - { - LOG.warn(e); - } - _sessions.remove(session.getClusterId()); - } - - //check if we should terminate our loop if we're not using the stop timer - if (stopTime == 0) - break; - - // Get any sessions that were added by other requests during processing and go around the loop again - sessions=new ArrayList(_sessions.values()); - } } /** - * - * @see org.eclipse.jetty.server.SessionManager#renewSessionId(java.lang.String, java.lang.String, java.lang.String, java.lang.String) - */ - public void renewSessionId (String oldClusterId, String oldNodeId, String newClusterId, String newNodeId) - { - Session session = null; - try - { - session = (Session)_sessions.remove(oldClusterId); - if (session != null) - { - synchronized (session) - { - session.setClusterId(newClusterId); //update ids - session.setNodeId(newNodeId); - _sessions.put(newClusterId, session); //put it into list in memory - updateSession(session); //update database - } - } - } - catch (Exception e) - { - LOG.warn(e); - } - - super.renewSessionId(oldClusterId, oldNodeId, newClusterId, newNodeId); - } - - - - /** - * Invalidate a session. - * - * @param idInCluster the id in the cluster - */ - @Override - public void invalidateSession (String idInCluster) - { - Session session = (Session)_sessions.get(idInCluster); - - if (session != null) - { - session.invalidate(); - } - } - - /** - * Delete an existing session, both from the in-memory map and - * the database. - * - * @see org.eclipse.jetty.server.session.AbstractSessionManager#removeSession(java.lang.String) - */ - @Override - protected boolean removeSession(String idInCluster) - { - Session session = (Session)_sessions.remove(idInCluster); - try - { - if (session != null) - deleteSession(session); - } - catch (Exception e) - { - LOG.warn("Problem deleting session id="+idInCluster, e); - } - return session!=null; - } - - - /** - * Add a newly created session to our in-memory list for this node and persist it. - * - * @see org.eclipse.jetty.server.session.AbstractSessionManager#addSession(org.eclipse.jetty.server.session.AbstractSession) - */ - @Override - protected void addSession(AbstractSession session) - { - if (session==null) - return; - - _sessions.put(session.getClusterId(), (Session)session); - - try - { - synchronized (session) - { - session.willPassivate(); - storeSession(((JDBCSessionManager.Session)session)); - session.didActivate(); - } - } - catch (Exception e) - { - LOG.warn("Unable to store new session id="+session.getId() , e); - } - } - - - /** - * Make a new Session. - * - * @see org.eclipse.jetty.server.session.AbstractSessionManager#newSession(javax.servlet.http.HttpServletRequest) - */ - @Override - protected AbstractSession newSession(HttpServletRequest request) - { - return new Session(request); - } - - protected AbstractSession newSession (String sessionId, String rowId, long created, long accessed, long maxInterval) - { - return new Session(sessionId, rowId, created, accessed, maxInterval); - } - - /* ------------------------------------------------------------ */ - /** Remove session from manager - * @param session The session to remove - * @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and - * {@link SessionIdManager#expireAll(String)} should be called. - */ - @Override - public boolean removeSession(AbstractSession session, boolean invalidate) - { - // Remove session from context and global maps - boolean removed = super.removeSession(session, invalidate); - - if (removed) - { - if (!invalidate) - { - session.willPassivate(); - } - } - - return removed; - } - - - /** - * Expire any Sessions we have in memory matching the list of - * expired Session ids. - * - * @param sessionIds the session ids to expire - * @return the set of successfully expired ids - */ - protected Set expire (Set sessionIds) - { - //don't attempt to scavenge if we are shutting down - if (isStopping() || isStopped()) - return null; - - - Thread thread=Thread.currentThread(); - ClassLoader old_loader=thread.getContextClassLoader(); - - Set successfullyExpiredIds = new HashSet(); - try - { - Iterator itor = sessionIds.iterator(); - while (itor.hasNext()) - { - String sessionId = (String)itor.next(); - if (LOG.isDebugEnabled()) - LOG.debug("Expiring session id "+sessionId); - - Session session = (Session)_sessions.get(sessionId); - - //if session is not in our memory, then fetch from db so we can call the usual listeners on it - if (session == null) - { - if (LOG.isDebugEnabled())LOG.debug("Force loading session id "+sessionId); - session = loadSession(sessionId, canonicalize(_context.getContextPath()), getVirtualHost(_context)); - if (session != null) - { - //loaded an expired session last managed on this node for this context, add it to the list so we can - //treat it like a normal expired session - _sessions.put(session.getClusterId(), session); - } - else - { - if (LOG.isDebugEnabled()) - LOG.debug("Unrecognized session id="+sessionId); - continue; - } - } - - if (session != null) - { - session.timeout(); - successfullyExpiredIds.add(session.getClusterId()); - } - } - return successfullyExpiredIds; - } - catch (Throwable t) - { - LOG.warn("Problem expiring sessions", t); - return successfullyExpiredIds; - } - finally - { - thread.setContextClassLoader(old_loader); - } - } - - - /** - * Load a session from the database - * @param id the id - * @param canonicalContextPath the canonical context path - * @param vhost the virtual host - * @return the session data that was loaded - * @throws Exception if unable to load the session - */ - protected Session loadSession (final String id, final String canonicalContextPath, final String vhost) - throws Exception - { - final AtomicReference _reference = new AtomicReference(); - final AtomicReference _exception = new AtomicReference(); - Runnable load = new Runnable() - { - /** - * @see java.lang.Runnable#run() - */ - @SuppressWarnings("unchecked") - public void run() - { - try (Connection connection = getConnection(); - PreparedStatement statement = _sessionTableSchema.getLoadStatement(connection, id, canonicalContextPath, vhost); - ResultSet result = statement.executeQuery()) - { - Session session = null; - if (result.next()) - { - long maxInterval = result.getLong(_sessionTableSchema.getMaxIntervalColumn()); - if (maxInterval == JDBCSessionIdManager.MAX_INTERVAL_NOT_SET) - { - maxInterval = getMaxInactiveInterval(); //if value not saved for maxInactiveInterval, use current value from sessionmanager - } - session = (Session)newSession(id, result.getString(_sessionTableSchema.getRowIdColumn()), - result.getLong(_sessionTableSchema.getCreateTimeColumn()), - result.getLong(_sessionTableSchema.getAccessTimeColumn()), - maxInterval); - session.setCookieSetTime(result.getLong(_sessionTableSchema.getCookieTimeColumn())); - session.setLastAccessedTime(result.getLong(_sessionTableSchema.getLastAccessTimeColumn())); - session.setLastNode(result.getString(_sessionTableSchema.getLastNodeColumn())); - session.setLastSaved(result.getLong(_sessionTableSchema.getLastSavedTimeColumn())); - session.setExpiryTime(result.getLong(_sessionTableSchema.getExpiryTimeColumn())); - session.setCanonicalContext(result.getString(_sessionTableSchema.getContextPathColumn())); - session.setVirtualHost(result.getString(_sessionTableSchema.getVirtualHostColumn())); - - try (InputStream is = ((JDBCSessionIdManager)getSessionIdManager())._dbAdaptor.getBlobInputStream(result, _sessionTableSchema.getMapColumn()); - ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is)) - { - Object o = ois.readObject(); - session.addAttributes((Map)o); - } - - if (LOG.isDebugEnabled()) - LOG.debug("LOADED session "+session); - } - else - if (LOG.isDebugEnabled()) - LOG.debug("Failed to load session "+id); - _reference.set(session); - } - catch (Exception e) - { - _exception.set(e); - } - } - }; - - if (_context==null) - load.run(); - else - _context.getContextHandler().handle(null,load); - - if (_exception.get()!=null) - { - //if the session could not be restored, take its id out of the pool of currently-in-use - //session ids - _jdbcSessionIdMgr.removeId(id); - throw _exception.get(); - } - - return _reference.get(); - } - - /** - * Insert a session into the database. - * - * @param session the session - * @throws Exception if unable to store the session - */ - protected void storeSession (Session session) - throws Exception - { - if (session==null) - return; - - //put into the database - try (Connection connection = getConnection(); - PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._insertSession)) - { - String rowId = calculateRowId(session); - - long now = System.currentTimeMillis(); - connection.setAutoCommit(true); - statement.setString(1, rowId); //rowId - statement.setString(2, session.getClusterId()); //session id - statement.setString(3, session.getCanonicalContext()); //context path - statement.setString(4, session.getVirtualHost()); //first vhost - statement.setString(5, getSessionIdManager().getWorkerName());//my node id - statement.setLong(6, session.getAccessed());//accessTime - statement.setLong(7, session.getLastAccessedTime()); //lastAccessTime - statement.setLong(8, session.getCreationTime()); //time created - statement.setLong(9, session.getCookieSetTime());//time cookie was set - statement.setLong(10, now); //last saved time - statement.setLong(11, session.getExpiryTime()); - statement.setLong(12, session.getMaxInactiveInterval()); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(session.getAttributeMap()); - oos.flush(); - byte[] bytes = baos.toByteArray(); - - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - statement.setBinaryStream(13, bais, bytes.length);//attribute map as blob - - - statement.executeUpdate(); - session.setRowId(rowId); //set it on the in-memory data as well as in db - session.setLastSaved(now); - } - if (LOG.isDebugEnabled()) - LOG.debug("Stored session "+session); - } - - - /** - * Update data on an existing persisted session. - * - * @param data the session - * @throws Exception if unable to update the session - */ - protected void updateSession (Session data) - throws Exception - { - if (data==null) - return; - - try (Connection connection = getConnection(); - PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._updateSession)) - { - long now = System.currentTimeMillis(); - connection.setAutoCommit(true); - statement.setString(1, data.getClusterId()); - statement.setString(2, getSessionIdManager().getWorkerName());//my node id - statement.setLong(3, data.getAccessed());//accessTime - statement.setLong(4, data.getLastAccessedTime()); //lastAccessTime - statement.setLong(5, now); //last saved time - statement.setLong(6, data.getExpiryTime()); - statement.setLong(7, data.getMaxInactiveInterval()); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(data.getAttributeMap()); - oos.flush(); - byte[] bytes = baos.toByteArray(); - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - - statement.setBinaryStream(8, bais, bytes.length);//attribute map as blob - statement.setString(9, data.getRowId()); //rowId - statement.executeUpdate(); - - data.setLastSaved(now); - } - if (LOG.isDebugEnabled()) - LOG.debug("Updated session "+data); - } - - - /** - * Update the node on which the session was last seen to be my node. - * - * @param data the session - * @throws Exception if unable to update the session node - */ - protected void updateSessionNode (Session data) - throws Exception - { - String nodeId = getSessionIdManager().getWorkerName(); - try (Connection connection = getConnection(); - PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._updateSessionNode)) - { - connection.setAutoCommit(true); - statement.setString(1, nodeId); - statement.setString(2, data.getRowId()); - statement.executeUpdate(); - } - if (LOG.isDebugEnabled()) - LOG.debug("Updated last node for session id="+data.getId()+", lastNode = "+nodeId); - } - - /** - * Persist the time the session was last accessed. - * - * @param data the session - * @throws Exception - */ - private void updateSessionAccessTime (Session data) - throws Exception - { - try (Connection connection = getConnection(); - PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._updateSessionAccessTime)) - { - long now = System.currentTimeMillis(); - connection.setAutoCommit(true); - statement.setString(1, getSessionIdManager().getWorkerName()); - statement.setLong(2, data.getAccessed()); - statement.setLong(3, data.getLastAccessedTime()); - statement.setLong(4, now); - statement.setLong(5, data.getExpiryTime()); - statement.setLong(6, data.getMaxInactiveInterval()); - statement.setString(7, data.getRowId()); - - statement.executeUpdate(); - data.setLastSaved(now); - } - if (LOG.isDebugEnabled()) - LOG.debug("Updated access time session id="+data.getId()+" with lastsaved="+data.getLastSaved()); - } - - - - - /** - * Delete a session from the database. Should only be called - * when the session has been invalidated. - * - * @param data the session data - * @throws Exception if unable to delete the session - */ - protected void deleteSession (Session data) - throws Exception - { - try (Connection connection = getConnection(); - PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._deleteSession)) - { - connection.setAutoCommit(true); - statement.setString(1, data.getRowId()); - statement.executeUpdate(); - if (LOG.isDebugEnabled()) - LOG.debug("Deleted Session "+data); - } - } - - - - /** - * Get a connection from the driver. - * @return - * @throws SQLException - */ - private Connection getConnection () - throws SQLException - { - return ((JDBCSessionIdManager)getSessionIdManager()).getConnection(); - } - - /** - * Calculate a unique id for this session across the cluster. - * - * Unique id is composed of: contextpath_virtualhost0_sessionid - * @param data + * Get the db adaptor to configure jdbc settings * @return */ - private String calculateRowId (Session data) + public DatabaseAdaptor getDatabaseAdaptor() { - String rowId = canonicalize(_context.getContextPath()); - rowId = rowId + "_" + getVirtualHost(_context); - rowId = rowId+"_"+data.getId(); - return rowId; + return _db; } - + /** - * Get the first virtual host for the context. - * - * Used to help identify the exact session/contextPath. - * - * @return 0.0.0.0 if no virtual host is defined - */ - private static String getVirtualHost (ContextHandler.Context context) - { - String vhost = "0.0.0.0"; - - if (context==null) - return vhost; - - String [] vhosts = context.getContextHandler().getVirtualHosts(); - if (vhosts==null || vhosts.length==0 || vhosts[0]==null) - return vhost; - - return vhosts[0]; - } - - /** - * Make an acceptable file name from a context path. - * - * @param path + * Get the SessionDataStore to configure it * @return */ - private static String canonicalize (String path) + public JDBCSessionDataStore getSessionDataStore () { - if (path==null) - return ""; - - return path.replace('/', '_').replace('.','_').replace('\\','_'); + return _sessionDataStore; } + } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java deleted file mode 100644 index b2322d62669..00000000000 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemSession.java +++ /dev/null @@ -1,146 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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 java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -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.http.HttpServletRequest; - - -/** - * MemSession - * - * A session whose data is kept in memory - */ -public class MemSession extends AbstractSession -{ - - private final Map _attributes=new HashMap(); - - protected MemSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request) - { - super(abstractSessionManager, request); - } - - public MemSession(AbstractSessionManager abstractSessionManager, long created, long accessed, String clusterId) - { - super(abstractSessionManager, created, accessed, clusterId); - } - - - /* ------------------------------------------------------------- */ - @Override - public Map getAttributeMap() - { - return _attributes; - } - - - /* ------------------------------------------------------------ */ - @Override - public int getAttributes() - { - synchronized (this) - { - checkValid(); - return _attributes.size(); - } - } - - /* ------------------------------------------------------------ */ - @SuppressWarnings({ "unchecked" }) - @Override - public Enumeration doGetAttributeNames() - { - List names=_attributes==null?Collections.EMPTY_LIST:new ArrayList(_attributes.keySet()); - return Collections.enumeration(names); - } - - - /* ------------------------------------------------------------ */ - @Override - public Set getNames() - { - synchronized (this) - { - return new HashSet(_attributes.keySet()); - } - } - - - /* ------------------------------------------------------------- */ - @Override - public void clearAttributes() - { - while (_attributes!=null && _attributes.size()>0) - { - ArrayList keys; - synchronized(this) - { - keys=new ArrayList(_attributes.keySet()); - } - - Iterator iter=keys.iterator(); - while (iter.hasNext()) - { - String key=(String)iter.next(); - - Object value; - synchronized(this) - { - value=doPutOrRemove(key,null); - } - unbindValue(key,value); - - ((AbstractSessionManager)getSessionManager()).doSessionAttributeListeners(this,key,value,null); - } - } - if (_attributes!=null) - _attributes.clear(); - } - - /* ------------------------------------------------------------ */ - public void addAttributes(Map map) - { - _attributes.putAll(map); - } - - /* ------------------------------------------------------------ */ - @Override - public Object doPutOrRemove(String name, Object value) - { - return value==null?_attributes.remove(name):_attributes.put(name,value); - } - - /* ------------------------------------------------------------ */ - @Override - public Object doGet(String name) - { - return _attributes.get(name); - } - -} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/MemorySessionStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemorySessionStore.java similarity index 88% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/MemorySessionStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/MemorySessionStore.java index e43bfb742af..cb5bb2dc5c1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/MemorySessionStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/MemorySessionStore.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.util.HashSet; import java.util.Set; @@ -82,7 +82,7 @@ public class MemorySessionStore extends AbstractSessionStore /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionStore#doGet(java.lang.String) + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doGet(java.lang.String) */ @Override public Session doGet(SessionKey key) @@ -101,7 +101,7 @@ public class MemorySessionStore extends AbstractSessionStore /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionStore#doPut(java.lang.String, org.eclipse.jetty.server.session.x.Session) + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doPut(java.lang.String, org.eclipse.jetty.server.session.Session) */ @Override public void doPut(SessionKey key, Session session) @@ -110,7 +110,7 @@ public class MemorySessionStore extends AbstractSessionStore } /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionStore#doExists(java.lang.String) + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doExists(java.lang.String) */ @Override public boolean doExists(SessionKey key) @@ -119,7 +119,7 @@ public class MemorySessionStore extends AbstractSessionStore } /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionStore#doDelete(java.lang.String) + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doDelete(java.lang.String) */ @Override public void doDelete(SessionKey key) @@ -194,7 +194,7 @@ public class MemorySessionStore extends AbstractSessionStore /** - * @see org.eclipse.jetty.server.session.x.SessionStore#newSession(java.lang.String) + * @see org.eclipse.jetty.server.session.SessionStore#newSession(java.lang.String) */ @Override public Session newSession(SessionKey key, long created, long accessed, long lastAccessed, long maxInactiveMs) @@ -206,7 +206,7 @@ public class MemorySessionStore extends AbstractSessionStore /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionStore#newSession(org.eclipse.jetty.server.session.x.SessionData) + * @see org.eclipse.jetty.server.session.AbstractSessionStore#newSession(org.eclipse.jetty.server.session.SessionData) */ @Override public Session newSession(SessionData data) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/NeverStaleStrategy.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/NeverStaleStrategy.java similarity index 86% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/NeverStaleStrategy.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/NeverStaleStrategy.java index 71dc964e78d..cc3549897ca 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/NeverStaleStrategy.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/NeverStaleStrategy.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; /** * NeverStale @@ -28,7 +28,7 @@ public class NeverStaleStrategy implements StalenessStrategy { /** - * @see org.eclipse.jetty.server.session.x.StalenessStrategy#isStale(org.eclipse.jetty.server.session.x.Session) + * @see org.eclipse.jetty.server.session.StalenessStrategy#isStale(org.eclipse.jetty.server.session.Session) */ @Override public boolean isStale(Session session) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/NullSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/NullSessionDataStore.java similarity index 76% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/NullSessionDataStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/NullSessionDataStore.java index 5a004601b19..32b7f078465 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/NullSessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/NullSessionDataStore.java @@ -17,9 +17,8 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; -import java.util.Collections; import java.util.Set; /** @@ -31,7 +30,7 @@ public class NullSessionDataStore extends AbstractSessionDataStore { /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#load(java.lang.String) + * @see org.eclipse.jetty.server.session.SessionDataStore#load(java.lang.String) */ @Override public SessionData load(SessionKey key) throws Exception @@ -41,7 +40,7 @@ public class NullSessionDataStore extends AbstractSessionDataStore /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.x.SessionKey, long, long, long, long) + * @see org.eclipse.jetty.server.session.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.SessionKey, long, long, long, long) */ @Override public SessionData newSessionData(SessionKey key, long created, long accessed, long lastAccessed, long maxInactiveMs) @@ -50,7 +49,7 @@ public class NullSessionDataStore extends AbstractSessionDataStore } /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#delete(java.lang.String) + * @see org.eclipse.jetty.server.session.SessionDataStore#delete(java.lang.String) */ @Override public boolean delete(SessionKey key) throws Exception @@ -59,7 +58,7 @@ public class NullSessionDataStore extends AbstractSessionDataStore } /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionDataStore#doStore() + * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore() */ @Override public void doStore(SessionKey key, SessionData data) throws Exception @@ -68,7 +67,7 @@ public class NullSessionDataStore extends AbstractSessionDataStore } /** - * @see org.eclipse.jetty.server.session.x.SessionDataStore#getExpired() + * @see org.eclipse.jetty.server.session.SessionDataStore#getExpired() */ @Override public Set getExpired(Set candidates) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/Session.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/Session.java similarity index 98% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/Session.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/Session.java index 5dd7759401a..37f50f57995 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/Session.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/Session.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.util.ArrayList; import java.util.Enumeration; @@ -32,6 +32,7 @@ import javax.servlet.http.HttpSessionBindingListener; import javax.servlet.http.HttpSessionContext; import javax.servlet.http.HttpSessionEvent; +import org.eclipse.jetty.server.session.SessionManager.SessionIf; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -387,6 +388,13 @@ public class Session implements SessionManager.SessionIf return SessionManager.__nullSessionContext; } + + public SessionManager getSessionManager() + { + return _manager; + } + + /* ------------------------------------------------------------- */ /** * asserts that the session is valid diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionData.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionData.java similarity index 99% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionData.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionData.java index e093af05e33..c3edae22343 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionData.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionData.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.io.IOException; import java.io.Serializable; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionDataStore.java similarity index 98% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionDataStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionDataStore.java index 9e4c9efec73..f62e3301c13 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionDataStore.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.util.Set; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionKey.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionKey.java similarity index 98% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionKey.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionKey.java index 394eb2bafc1..804ebf2237f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionKey.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionKey.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import org.eclipse.jetty.server.handler.ContextHandler.Context; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionManager.java similarity index 99% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionManager.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionManager.java index a75f92d6d48..ba8c87a13ce 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionManager.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionManager.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import static java.lang.Math.round; @@ -46,8 +46,6 @@ import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.SessionIdManager; import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.session.HashSessionIdManager; -import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedOperation; @@ -507,7 +505,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je { String sessionPath = (_cookieConfig.getPath()==null) ? contextPath : _cookieConfig.getPath(); sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath; - String id = getNodeId(session); + String id = getExtendedId(session); HttpCookie cookie = null; if (_sessionComment == null) { @@ -596,7 +594,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je /* ------------------------------------------------------------ */ @Override - public String getClusterId(HttpSession session) + public String getId(HttpSession session) { Session s = ((SessionIf)session).getSession(); return s.getId(); @@ -604,7 +602,7 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je /* ------------------------------------------------------------ */ @Override - public String getNodeId(HttpSession session) + public String getExtendedId(HttpSession session) { Session s = ((SessionIf)session).getSession(); return s.getExtendedId(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionScavenger.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionScavenger.java similarity index 97% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionScavenger.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionScavenger.java index c7d3c02dd27..a58a59278b2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionScavenger.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionScavenger.java @@ -17,16 +17,14 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.util.Set; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.SessionIdManager; import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionStore.java similarity index 97% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionStore.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionStore.java index 123e72ecd6c..855313bf9af 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/SessionStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionStore.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; import java.util.Set; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/StalePeriodStrategy.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/StalePeriodStrategy.java similarity index 91% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/StalePeriodStrategy.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/StalePeriodStrategy.java index 874b0da681f..84475568603 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/StalePeriodStrategy.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/StalePeriodStrategy.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; /** * StalePeriodStrategy @@ -29,7 +29,7 @@ public class StalePeriodStrategy implements StalenessStrategy protected long _staleMs = 0; /** - * @see org.eclipse.jetty.server.session.x.StalenessStrategy#isStale(org.eclipse.jetty.server.session.x.Session) + * @see org.eclipse.jetty.server.session.StalenessStrategy#isStale(org.eclipse.jetty.server.session.Session) */ @Override public boolean isStale (Session session) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/StalenessStrategy.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/StalenessStrategy.java similarity index 95% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/StalenessStrategy.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/StalenessStrategy.java index ac19c85267f..e23c7d8b23e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/StalenessStrategy.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/StalenessStrategy.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; /** * StalenessStrategy diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/UnreadableSessionDataException.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/UnreadableSessionDataException.java similarity index 96% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/UnreadableSessionDataException.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/UnreadableSessionDataException.java index 0cb62b0dcb2..ff9a0d12719 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/UnreadableSessionDataException.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/UnreadableSessionDataException.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; /** * UnreadableSessionData diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/UnwriteableSessionDataException.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/UnwriteableSessionDataException.java similarity index 96% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/x/UnwriteableSessionDataException.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/UnwriteableSessionDataException.java index 955900c56a3..50422ce5a7c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/UnwriteableSessionDataException.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/UnwriteableSessionDataException.java @@ -17,7 +17,7 @@ // -package org.eclipse.jetty.server.session.x; +package org.eclipse.jetty.server.session; /** * UnwriteableSessionDataException diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/jmx/AbstractSessionManagerMBean.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/jmx/SessionManagerMBean.java similarity index 84% rename from jetty-server/src/main/java/org/eclipse/jetty/server/session/jmx/AbstractSessionManagerMBean.java rename to jetty-server/src/main/java/org/eclipse/jetty/server/session/jmx/SessionManagerMBean.java index 377ddc36a8b..b3c2e9ff19d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/jmx/AbstractSessionManagerMBean.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/jmx/SessionManagerMBean.java @@ -21,12 +21,12 @@ package org.eclipse.jetty.server.session.jmx; import org.eclipse.jetty.server.handler.AbstractHandlerContainer; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.jmx.AbstractHandlerMBean; -import org.eclipse.jetty.server.session.AbstractSessionManager; +import org.eclipse.jetty.server.session.SessionManager; import org.eclipse.jetty.server.session.SessionHandler; -public class AbstractSessionManagerMBean extends AbstractHandlerMBean +public class SessionManagerMBean extends AbstractHandlerMBean { - public AbstractSessionManagerMBean(Object managedObject) + public SessionManagerMBean(Object managedObject) { super(managedObject); } @@ -34,9 +34,9 @@ public class AbstractSessionManagerMBean extends AbstractHandlerMBean /* ------------------------------------------------------------ */ public String getObjectContextBasis() { - if (_managed != null && _managed instanceof AbstractSessionManager) + if (_managed != null && _managed instanceof SessionManager) { - AbstractSessionManager manager = (AbstractSessionManager)_managed; + SessionManager manager = (SessionManager)_managed; String basis = null; SessionHandler handler = manager.getSessionHandler(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionIdManager.java deleted file mode 100644 index 1a89617b97c..00000000000 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/AbstractSessionIdManager.java +++ /dev/null @@ -1,393 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.x; - -import java.security.SecureRandom; -import java.util.Random; - -import javax.servlet.http.HttpServletRequest; - -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.SessionIdManager; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.util.component.AbstractLifeCycle; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; - -public abstract class AbstractSessionIdManager extends AbstractLifeCycle implements SessionIdManager -{ - private static final Logger LOG = Log.getLogger(AbstractSessionIdManager.class); - - private final static String __NEW_SESSION_ID="org.eclipse.jetty.server.newSessionId"; - - protected Random _random; - protected boolean _weakRandom; - protected String _workerName; - protected String _workerAttr; - protected long _reseed=100000L; - protected Server _server; - protected SessionScavenger _scavenger; - - /* ------------------------------------------------------------ */ - public AbstractSessionIdManager() - { - } - - /* ------------------------------------------------------------ */ - public AbstractSessionIdManager(Random random) - { - _random=random; - } - - - public void setServer (Server server) - { - _server = server; - } - - public Server getServer () - { - return _server; - } - - - public void setSessionScavenger (SessionScavenger scavenger) - { - _scavenger = scavenger; - _scavenger.setSessionIdManager(this); - } - - - - /* ------------------------------------------------------------ */ - /** - * Get the workname. If set, the workername is dot appended to the session - * ID and can be used to assist session affinity in a load balancer. - * - * @return String or null - */ - @Override - public String getWorkerName() - { - return _workerName; - } - - - - /* ------------------------------------------------------------ */ - /** - * Set the workername. If set, the workername is dot appended to the session - * ID and can be used to assist session affinity in a load balancer. - * A worker name starting with $ is used as a request attribute name to - * lookup the worker name that can be dynamically set by a request - * Customizer. - * - * @param workerName the name of the worker - */ - public void setWorkerName(String workerName) - { - if (isRunning()) - throw new IllegalStateException(getState()); - if (workerName.contains(".")) - throw new IllegalArgumentException("Name cannot contain '.'"); - _workerName=workerName; - } - - /* ------------------------------------------------------------ */ - public Random getRandom() - { - return _random; - } - - /* ------------------------------------------------------------ */ - public synchronized void setRandom(Random random) - { - _random=random; - _weakRandom=false; - } - - /* ------------------------------------------------------------ */ - /** - * @return the reseed probability - */ - public long getReseed() - { - return _reseed; - } - - /* ------------------------------------------------------------ */ - /** Set the reseed probability. - * @param reseed If non zero then when a random long modulo the reseed value == 1, the {@link SecureRandom} will be reseeded. - */ - public void setReseed(long reseed) - { - _reseed = reseed; - } - - /* ------------------------------------------------------------ */ - /** - * Create a new session id if necessary. - * - * @see org.eclipse.jetty.server.SessionIdManager#newSessionId(javax.servlet.http.HttpServletRequest, long) - */ - @Override - public String newSessionId(HttpServletRequest request, long created) - { - synchronized (this) - { - if (request==null) - return newSessionId(created); - - // A requested session ID can only be used if it is in use already. - String requested_id=request.getRequestedSessionId(); - if (requested_id!=null) - { - String cluster_id=getId(requested_id); - if (isIdInUse(cluster_id)) - return cluster_id; - } - - // Else reuse any new session ID already defined for this request. - String new_id=(String)request.getAttribute(__NEW_SESSION_ID); - if (new_id!=null&&isIdInUse(new_id)) - return new_id; - - // pick a new unique ID! - String id = newSessionId(request.hashCode()); - - request.setAttribute(__NEW_SESSION_ID,id); - return id; - } - } - - /* ------------------------------------------------------------ */ - public String newSessionId(long seedTerm) - { - // pick a new unique ID! - String id=null; - while (id==null||id.length()==0||isIdInUse(id)) - { - long r0=_weakRandom - ?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^((seedTerm)<<32)) - :_random.nextLong(); - if (r0<0) - r0=-r0; - - // random chance to reseed - if (_reseed>0 && (r0%_reseed)== 1L) - { - if (LOG.isDebugEnabled()) - LOG.debug("Reseeding {}",this); - if (_random instanceof SecureRandom) - { - SecureRandom secure = (SecureRandom)_random; - secure.setSeed(secure.generateSeed(8)); - } - else - { - _random.setSeed(_random.nextLong()^System.currentTimeMillis()^seedTerm^Runtime.getRuntime().freeMemory()); - } - } - - long r1=_weakRandom - ?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^((seedTerm)<<32)) - :_random.nextLong(); - if (r1<0) - r1=-r1; - - id=Long.toString(r0,36)+Long.toString(r1,36); - - //add in the id of the node to ensure unique id across cluster - //NOTE this is different to the node suffix which denotes which node the request was received on - if (_workerName!=null) - id=_workerName + id; - - } - return id; - } - - - - - /* ------------------------------------------------------------ */ - @Override - protected void doStart() throws Exception - { - if (_server == null) - throw new IllegalStateException("No Server for SessionIdManager"); - initRandom(); - _workerAttr=(_workerName!=null && _workerName.startsWith("$"))?_workerName.substring(1):null; - - if (_scavenger == null) - { - LOG.warn("No SessionScavenger set, using defaults"); - _scavenger = new SessionScavenger(); - _scavenger.setSessionIdManager(this); - } - - _scavenger.start(); - } - - /* ------------------------------------------------------------ */ - @Override - protected void doStop() throws Exception - { - _scavenger.stop(); - } - - /* ------------------------------------------------------------ */ - /** - * Set up a random number generator for the sessionids. - * - * By preference, use a SecureRandom but allow to be injected. - */ - public void initRandom () - { - if (_random==null) - { - try - { - _random=new SecureRandom(); - } - catch (Exception e) - { - LOG.warn("Could not generate SecureRandom for session-id randomness",e); - _random=new Random(); - _weakRandom=true; - } - } - else - _random.setSeed(_random.nextLong()^System.currentTimeMillis()^hashCode()^Runtime.getRuntime().freeMemory()); - } - - /** Get the session ID with any worker ID. - * - * @param clusterId the cluster id - * @param request the request - * @return sessionId plus any worker ID. - */ - @Override - public String getExtendedId(String clusterId, HttpServletRequest request) - { - if (_workerName!=null) - { - if (_workerAttr==null) - return clusterId+'.'+_workerName; - - String worker=(String)request.getAttribute(_workerAttr); - if (worker!=null) - return clusterId+'.'+worker; - } - - return clusterId; - } - - /** Get the session ID without any worker ID. - * - * @param extendedId the session id with the worker extension - * @return sessionId without any worker ID. - */ - @Override - public String getId(String extendedId) - { - int dot=extendedId.lastIndexOf('.'); - return (dot>0)?extendedId.substring(0,dot):extendedId; - } - - /** - * Remove an id from use by telling all contexts to remove a session with this id. - * - * @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String) - */ - @Override - public void expireAll(String id) - { - //take the id out of the list of known sessionids for this node - removeId(id); - - //tell all contexts that may have a session object with this id to - //get rid of them - Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class); - for (int i=0; contexts!=null && i _ids = new ConcurrentHashSet(); - - - /** - * @see org.eclipse.jetty.server.SessionIdManager#isIdInUse(java.lang.String) - */ - @Override - public boolean isIdInUse(String id) - { - return _ids.contains(id); - } - - - /** - * @see org.eclipse.jetty.server.session.x.AbstractSessionIdManager#newSessionId(long) - */ - @Override - public String newSessionId(long seedTerm) - { - String id = super.newSessionId(seedTerm); - useId(id); - return id; - } - - - /** - * @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String) - */ - @Override - public void useId(String id) - { - if (id == null) - return; - - _ids.add(id); - } - - /** - * @see org.eclipse.jetty.server.SessionIdManager#removeId(java.lang.String) - */ - @Override - public void removeId(String id) - { - _ids.remove(id); - } - -} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/HashSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/HashSessionManager.java deleted file mode 100644 index c96249a6461..00000000000 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/HashSessionManager.java +++ /dev/null @@ -1,56 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.x; - -/** - * HashSessionManager - * - * - */ -public class HashSessionManager extends SessionManager -{ - protected FileSessionDataStore _sessionDataStore = new FileSessionDataStore(); - - - @Override - public void doStart() throws Exception - { - _sessionStore = new MemorySessionStore(); - ((AbstractSessionStore)_sessionStore).setSessionDataStore(_sessionDataStore); - - super.doStart(); - } - - @Override - public void doStop() throws Exception - { - super.doStop(); - } - - /** - * Get the SessionDataStore to configure it - * @return - */ - public FileSessionDataStore getSessionDataStore() - { - return _sessionDataStore; - } - -} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionIdManager.java deleted file mode 100644 index e837c1f7458..00000000000 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/x/JDBCSessionIdManager.java +++ /dev/null @@ -1,439 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 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.x; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.sql.Blob; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.HashSet; -import java.util.Locale; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import javax.naming.InitialContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import javax.sql.DataSource; - -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.SessionManager; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; -import org.eclipse.jetty.util.thread.Scheduler; - - - -/** - * JDBCSessionIdManager - * - * SessionIdManager implementation that uses a database to store in-use session ids, - * to support distributed sessions. - * - */ -public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.x.AbstractSessionIdManager -{ - private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session"); - - public final static int MAX_INTERVAL_NOT_SET = -999; - - protected final HashSet _sessionIds = new HashSet(); - protected Server _server; - protected SessionScavenger _scavenger; - - private DatabaseAdaptor _dbAdaptor = new DatabaseAdaptor(); - - protected SessionIdTableSchema _sessionIdTableSchema = new SessionIdTableSchema(); - - /** - * SessionIdTableSchema - * - */ - public static class SessionIdTableSchema - { - protected String _tableName = "JettySessionIds"; - protected String _idColumn = "id"; - protected DatabaseAdaptor _jdbc; - - public String getIdColumn() - { - return _idColumn; - } - - public void setIdColumn(String idColumn) - { - checkNotNull(idColumn); - _idColumn = idColumn; - } - - public String getTableName() - { - return _tableName; - } - - public void setTableName(String tableName) - { - checkNotNull(tableName); - _tableName = tableName; - } - - public String getInsertStatementAsString () - { - return "insert into "+_tableName+" ("+_idColumn+") values (?)"; - } - - public String getDeleteStatementAsString () - { - return "delete from "+_tableName+" where "+_idColumn+" = ?"; - } - - public String getSelectStatementAsString () - { - return "select * from "+_tableName+" where "+_idColumn+" = ?"; - } - - public String getCreateStatementAsString () - { - return "create table "+_tableName+" ("+_idColumn+" varchar(120), primary key("+_idColumn+"))"; - } - - protected void prepareTables (DatabaseAdaptor jdbc) - throws Exception - { - _jdbc = jdbc; - try (Connection connection = _jdbc.getConnection(); - Statement statement = connection.createStatement()) - { - //make the id table - connection.setAutoCommit(true); - DatabaseMetaData metaData = connection.getMetaData(); - _jdbc.adaptTo(metaData); - - - //checking for table existence is case-sensitive, but table creation is not - String tableName = _jdbc.convertIdentifier(getTableName()); - try (ResultSet result = metaData.getTables(null, null, tableName, null)) - { - if (!result.next()) - { - //table does not exist, so create it - statement.executeUpdate(getCreateStatementAsString()); - } - } - } - } - - private void checkNotNull(String s) - { - if (s == null) - throw new IllegalArgumentException(s); - } - } - - - public JDBCSessionIdManager(Server server) - { - super(); - _server=server; - } - - public JDBCSessionIdManager(Server server, Random random) - { - super(random); - _server=server; - } - - public SessionIdTableSchema getSessionIdTableSchema() - { - return _sessionIdTableSchema; - } - - @Override - public String newSessionId(long seedTerm) - { - String id = super.newSessionId(seedTerm); - useId(id); - return id; - } - - - - /** - * Record the session id as being in use - * - * @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String) - */ - public void useId (String id) - { - if (id == null) - return; - - synchronized (_sessionIds) - { - try - { - insert(id); - _sessionIds.add(id); - } - catch (Exception e) - { - LOG.warn("Problem storing session id="+id, e); - } - } - } - - - - - /** - * Remove the id from in-use set - * - * Prevents another context from using this id - * - * @see org.eclipse.jetty.server.SessionIdManager#removeId(java.lang.String) - */ - @Override - public void removeId (String id) - { - - if (id == null) - return; - - synchronized (_sessionIds) - { - if (LOG.isDebugEnabled()) - LOG.debug("Removing sessionid="+id); - try - { - _sessionIds.remove(id); - delete(id); - } - catch (Exception e) - { - LOG.warn("Problem removing session id="+id, e); - } - } - - } - - /** - * Insert a new used session id into the table. - * - * @param id - * @throws SQLException - */ - private void insert (String id) - throws SQLException - { - try (Connection connection = _dbAdaptor.getConnection(); - PreparedStatement query = connection.prepareStatement(_sessionIdTableSchema.getSelectStatementAsString())) - { - connection.setAutoCommit(true); - query.setString(1, id); - try (ResultSet result = query.executeQuery()) - { - //only insert the id if it isn't in the db already - if (!result.next()) - { - try (PreparedStatement statement = connection.prepareStatement(_sessionIdTableSchema.getInsertStatementAsString())) - { - statement.setString(1, id); - statement.executeUpdate(); - } - } - } - } - } - - /** - * Remove a session id from the table. - * - * @param id - * @throws SQLException - */ - private void delete (String id) - throws SQLException - { - try (Connection connection = _dbAdaptor.getConnection(); - PreparedStatement statement = connection.prepareStatement(_sessionIdTableSchema.getDeleteStatementAsString())) - { - connection.setAutoCommit(true); - statement.setString(1, id); - statement.executeUpdate(); - } - } - - - /** - * Check if a session id exists. - * - * @param id - * @return - * @throws SQLException - */ - private boolean exists (String id) - throws SQLException - { - try (Connection connection = _dbAdaptor.getConnection(); - PreparedStatement statement = connection.prepareStatement(_sessionIdTableSchema.getSelectStatementAsString())) - { - connection.setAutoCommit(true); - statement.setString(1, id); - try (ResultSet result = statement.executeQuery()) - { - return result.next(); - } - } - } - - - @Override - public boolean isIdInUse(String id) - { - if (id == null) - return false; - - String sessionId = getId(id); - boolean inUse = false; - synchronized (_sessionIds) - { - inUse = _sessionIds.contains(sessionId); - } - - - if (inUse) - return true; //optimisation - if this session is one we've been managing, we can check locally - - //otherwise, we need to go to the database to check - try - { - return exists(sessionId); - } - catch (Exception e) - { - LOG.warn("Problem checking inUse for id="+sessionId, e); - return false; - } - } - - - /** - * Invalidate the session matching the id on all contexts. - * - * @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String) - */ - @Override - public void expireAll(String id) - { - synchronized (_sessionIds) - { - super.expireAll(id); - } - } - - - - @Override - public void renewSessionId(String oldClusterId, String oldNodeId, HttpServletRequest request) - { - synchronized (_sessionIds) - { - super.renewSessionId(oldClusterId, oldNodeId, request); - } - } - - /** - * Get the database adaptor in order to configure it - * @return - */ - public DatabaseAdaptor getDatabaseAdaptor () - { - return _dbAdaptor; - } - - - - - /** - * Start up the id manager. - * - * Makes necessary database tables and starts a Session - * scavenger thread. - */ - @Override - public void doStart() - throws Exception - { - _dbAdaptor.initialize(); - _sessionIdTableSchema.prepareTables(_dbAdaptor); - - super.doStart(); - - } - - /** - * Stop - */ - @Override - public void doStop () - throws Exception - { - _sessionIds.clear(); - - super.doStop(); - } - - - - /** - * - * @param sql - * @param atoms - * @throws Exception - */ - private String fillInClause (String sql, String[] literals, int start, int end) - throws Exception - { - StringBuffer buff = new StringBuffer(); - buff.append(sql); - buff.append("("); - for (int i=start; i getAttributeNames() - { - return null; - } - - @Override - public String[] getValueNames() - { - return null; - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSession#getAttributeMap() - */ - @Override - public Map getAttributeMap() - { - return null; - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSession#getAttributes() - */ - @Override - public int getAttributes() - { - return 0; - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSession#getNames() - */ - @Override - public Set getNames() - { - return null; - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSession#clearAttributes() - */ - @Override - public void clearAttributes() + public void shutdown() { + // TODO Auto-generated method stub } /** - * @see org.eclipse.jetty.server.session.AbstractSession#doPutOrRemove(java.lang.String, java.lang.Object) + * @see org.eclipse.jetty.server.session.AbstractSessionStore#newSession(org.eclipse.jetty.server.session.SessionData) */ @Override - public Object doPutOrRemove(String name, Object value) + public Session newSession(SessionData data) { + // TODO Auto-generated method stub return null; } /** - * @see org.eclipse.jetty.server.session.AbstractSession#doGet(java.lang.String) + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doGet(org.eclipse.jetty.server.session.SessionKey) */ @Override - public Object doGet(String name) + public Session doGet(SessionKey key) { + // TODO Auto-generated method stub return null; } /** - * @see org.eclipse.jetty.server.session.AbstractSession#doGetAttributeNames() + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doPut(org.eclipse.jetty.server.session.SessionKey, org.eclipse.jetty.server.session.Session) */ @Override - public Enumeration doGetAttributeNames() + public void doPut(SessionKey key, Session session) { - return null; + // TODO Auto-generated method stub + } + /** + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doExists(org.eclipse.jetty.server.session.SessionKey) + */ + @Override + public boolean doExists(SessionKey key) + { + // TODO Auto-generated method stub + return false; + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doDelete(org.eclipse.jetty.server.session.SessionKey) + */ + @Override + public void doDelete(SessionKey key) + { + // TODO Auto-generated method stub + + } + + /** + * @see org.eclipse.jetty.server.session.AbstractSessionStore#doGetExpiredCandidates() + */ + @Override + public Set doGetExpiredCandidates() + { + // TODO Auto-generated method stub + return null; + } } + + public class MockSessionIdManager extends AbstractSessionIdManager { @@ -145,24 +138,6 @@ public class SessionCookieTest return false; } - /** - * @see org.eclipse.jetty.server.SessionIdManager#addSession(javax.servlet.http.HttpSession) - */ - @Override - public void addSession(HttpSession session) - { - - } - - /** - * @see org.eclipse.jetty.server.SessionIdManager#removeSession(javax.servlet.http.HttpSession) - */ - @Override - public void removeSession(HttpSession session) - { - - } - /** * @see org.eclipse.jetty.server.SessionIdManager#expireAll(java.lang.String) */ @@ -179,64 +154,37 @@ public class SessionCookieTest } - } - - public class MockSessionManager extends AbstractSessionManager - { - - /** - * @see org.eclipse.jetty.server.session.AbstractSessionManager#addSession(org.eclipse.jetty.server.session.AbstractSession) + /** + * @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String) */ @Override - protected void addSession(AbstractSession session) - { - - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSessionManager#getSession(java.lang.String) - */ - @Override - public AbstractSession getSession(String idInCluster) - { - return null; - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSessionManager#shutdownSessions() - */ - @Override - protected void shutdownSessions() throws Exception - { - - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSessionManager#newSession(javax.servlet.http.HttpServletRequest) - */ - @Override - protected AbstractSession newSession(HttpServletRequest request) - { - return null; - } - - /** - * @see org.eclipse.jetty.server.session.AbstractSessionManager#removeSession(java.lang.String) - */ - @Override - protected boolean removeSession(String idInCluster) - { - return false; - } - - @Override - public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId) + public void useId(String id) { // TODO Auto-generated method stub } + /** + * @see org.eclipse.jetty.server.SessionIdManager#removeId(java.lang.String) + */ + @Override + public void removeId(String id) + { + // TODO Auto-generated method stub + + } } + + public class MockSessionManager extends SessionManager + { + public MockSessionManager() + { + _sessionStore = new MockSessionStore(); + ((AbstractSessionStore)_sessionStore).setSessionDataStore(new NullSessionDataStore()); + } + } + + @Test public void testSecureSessionCookie () throws Exception @@ -245,7 +193,10 @@ public class SessionCookieTest idMgr.setWorkerName("node1"); MockSessionManager mgr = new MockSessionManager(); mgr.setSessionIdManager(idMgr); - MockSession session = new MockSession(mgr, System.currentTimeMillis(), System.currentTimeMillis(), "node1123"); //clusterId + + long now = System.currentTimeMillis(); + + Session session = new Session(new SessionData("123", "_foo", "0.0.0.0", now, now, now, 30)); SessionCookieConfig sessionCookieConfig = mgr.getSessionCookieConfig(); sessionCookieConfig.setSecure(true);