Merge branch 'master' into performance

This commit is contained in:
Greg Wilkins 2011-07-12 17:44:03 +10:00
commit c61e490d8e
32 changed files with 1379 additions and 1063 deletions

View File

@ -1,3 +1,7 @@
jetty-7.5.0-SNAPSHOT
+ 351516 Refactored sessions to better support nosql session managers
+ 351576 Do not use deprecated method File.toURL()
jetty-7.4.4.v20110707 July 7th 2011
+ 308851 Converted all jetty-client module tests to JUnit 4
+ 345268 JDBCSessionManager does not work with maxInactiveInterval = -1

View File

@ -219,7 +219,7 @@ public class ContextDeployer extends AbstractLifeCycle
@Deprecated
public void setConfigurationDir(File file) throws Exception
{
setConfigurationDir(Resource.newResource(file.toURL()));
setConfigurationDir(Resource.newResource(Resource.toURL(file)));
}
/* ------------------------------------------------------------ */

View File

@ -52,7 +52,7 @@ public class MockAppProvider extends AbstractLifeCycle implements AppProvider
WebAppContext context = new WebAppContext();
File war = new File(webappsDir,app.getOriginId().substring(5));
context.setWar(Resource.newResource(war.toURI().toURL()).toString());
context.setWar(Resource.newResource(Resource.toURL(war)).toString());
String path = war.getName();

View File

@ -42,6 +42,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.PathAssert;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.Assert;
@ -132,7 +133,7 @@ public class XmlConfiguredJetty
public void addConfiguration(File xmlConfigFile) throws MalformedURLException
{
_xmlConfigurations.add(xmlConfigFile.toURI().toURL());
_xmlConfigurations.add(Resource.toURL(xmlConfigFile));
}
public void addConfiguration(String testConfigName) throws MalformedURLException

View File

@ -1108,31 +1108,25 @@ public class Request implements HttpServletRequest
* @see javax.servlet.http.HttpServletRequest#getSession(boolean)
*/
public HttpSession getSession(boolean create)
{
if (_sessionManager==null && create)
{
if (_session != null )
{
if (_sessionManager!=null && !_sessionManager.isValid(_session))
_session=null;
else
return _session;
}
if (!create)
return null;
if (_sessionManager==null)
throw new IllegalStateException("No SessionManager");
if (_session != null && _sessionManager!=null && _sessionManager.isValid(_session))
return _session;
_session=null;
String id=getRequestedSessionId();
if (id != null && _sessionManager!=null)
{
_session=_sessionManager.getHttpSession(id);
if (_session == null && !create)
return null;
}
if (_session == null && _sessionManager!=null && create )
{
_session=_sessionManager.newHttpSession(this);
HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
if (cookie!=null)
_connection.getResponse().addCookie(cookie);
}
_session=_sessionManager.newHttpSession(this);
HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
if (cookie!=null)
_connection.getResponse().addCookie(cookie);
return _session;
}
@ -1292,7 +1286,7 @@ public class Request implements HttpServletRequest
return false;
HttpSession session=getSession(false);
return (session != null && _sessionManager.getIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
}
/* ------------------------------------------------------------ */

View File

@ -187,14 +187,14 @@ public interface SessionManager extends LifeCycle
/* ------------------------------------------------------------ */
/**
* @return the cross context session id manager.
* @see #setIdManager(SessionIdManager)
* @see #setSessionIdManager(SessionIdManager)
*/
public SessionIdManager getIdManager();
public SessionIdManager getSessionIdManager();
/* ------------------------------------------------------------ */
/**
* @return the cross context session id manager.
* @deprecated use {@link #getIdManager()}
* @deprecated use {@link #getSessionIdManager()}
*/
@Deprecated
public SessionIdManager getMetaManager();
@ -204,9 +204,9 @@ public interface SessionManager extends LifeCycle
* Sets the cross context session id manager
*
* @param idManager the cross context session id manager.
* @see #getIdManager()
* @see #getSessionIdManager()
*/
public void setIdManager(SessionIdManager idManager);
public void setSessionIdManager(SessionIdManager idManager);
/* ------------------------------------------------------------ */
/**

View File

@ -0,0 +1,525 @@
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.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.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
*
* <p>
* Implements {@link javax.servlet.http.HttpSession} from the <code>javax.servlet</code> package.
* </p>
*
*/
@SuppressWarnings("deprecation")
public abstract class AbstractSession implements AbstractSessionManager.SessionIf
{
final static Logger __log = SessionHandler.__log;
private final AbstractSessionManager _manager;
private final String _clusterId; // ID unique within cluster
private final String _nodeId; // ID unique within node
private final Map<String,Object> _attributes=new HashMap<String, Object>();
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;
// TODO remove this.
protected final Map<String,Object> _jdbcAttributes=_attributes;
/* ------------------------------------------------------------- */
protected AbstractSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request)
{
_manager = abstractSessionManager;
_newSession=true;
_created=System.currentTimeMillis();
_clusterId=_manager._sessionIdManager.newSessionId(request,_created);
_nodeId=_manager._sessionIdManager.getNodeId(_clusterId,request);
_accessed=_created;
_lastAccessed=_created;
_requests=1;
_maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000:-1;
__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.getNodeId(_clusterId,null);
_accessed=accessed;
_lastAccessed=accessed;
_requests=1;
__log.debug("new session "+_nodeId+" "+_clusterId);
}
/* ------------------------------------------------------------- */
/**
* @return True is the session is invalid or passivated.
*/
protected void checkValid() throws IllegalStateException
{
if (_invalid)
throw new IllegalStateException();
}
/* ------------------------------------------------------------- */
public AbstractSession getSession()
{
return this;
}
/* ------------------------------------------------------------- */
public long getAccessed()
{
synchronized (this)
{
return _accessed;
}
}
/* ------------------------------------------------------------ */
public Object getAttribute(String name)
{
synchronized (this)
{
checkValid();
return _attributes.get(name);
}
}
/* ------------------------------------------------------------ */
public int getAttributes()
{
synchronized (this)
{
checkValid();
return _attributes.size();
}
}
/* ------------------------------------------------------------ */
@SuppressWarnings({ "rawtypes", "unchecked" })
public Enumeration getAttributeNames()
{
synchronized (this)
{
checkValid();
List names=_attributes==null?Collections.EMPTY_LIST:new ArrayList(_attributes.keySet());
return Collections.enumeration(names);
}
}
/* ------------------------------------------------------------ */
public Set<String> getNames()
{
synchronized (this)
{
return new HashSet<String>(_attributes.keySet());
}
}
/* ------------------------------------------------------------- */
public long getCookieSetTime()
{
return _cookieSet;
}
/* ------------------------------------------------------------- */
public long getCreationTime() throws IllegalStateException
{
return _created;
}
/* ------------------------------------------------------------ */
public String getId() throws IllegalStateException
{
return _manager._nodeIdInSessionId?_nodeId:_clusterId;
}
/* ------------------------------------------------------------- */
public String getNodeId()
{
return _nodeId;
}
/* ------------------------------------------------------------- */
public String getClusterId()
{
return _clusterId;
}
/* ------------------------------------------------------------- */
public long getLastAccessedTime() throws IllegalStateException
{
checkValid();
return _lastAccessed;
}
/* ------------------------------------------------------------- */
public int getMaxInactiveInterval()
{
checkValid();
return (int)(_maxIdleMs/1000);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpSession#getServletContext()
*/
public ServletContext getServletContext()
{
return _manager._context;
}
/* ------------------------------------------------------------- */
@Deprecated
public HttpSessionContext getSessionContext() throws IllegalStateException
{
checkValid();
return AbstractSessionManager.__nullSessionContext;
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #getAttribute}
*/
@Deprecated
public Object getValue(String name) throws IllegalStateException
{
return getAttribute(name);
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #getAttributeNames}
*/
@Deprecated
public String[] getValueNames() throws IllegalStateException
{
synchronized(this)
{
checkValid();
if (_attributes==null)
return new String[0];
String[] a=new String[_attributes.size()];
return (String[])_attributes.keySet().toArray(a);
}
}
/* ------------------------------------------------------------ */
protected boolean access(long time)
{
synchronized(this)
{
if (_invalid)
return false;
_newSession=false;
_lastAccessed=_accessed;
_accessed=time;
if (_maxIdleMs>0 && _lastAccessed>0 && _lastAccessed + _maxIdleMs < 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
synchronized (this)
{
if (!_invalid)
{
if (_requests<=0)
doInvalidate();
else
_doInvalidate=true;
}
}
}
/* ------------------------------------------------------------- */
public void invalidate() throws IllegalStateException
{
// remove session from context and invalidate other sessions with same ID.
_manager.removeSession(this,true);
doInvalidate();
}
/* ------------------------------------------------------------- */
protected void doInvalidate() throws IllegalStateException
{
try
{
__log.debug("invalidate ",_clusterId);
if (isValid())
clearAttributes();
}
finally
{
synchronized (this)
{
// mark as invalid
_invalid=true;
}
}
}
/* ------------------------------------------------------------- */
public void clearAttributes()
{
while (_attributes!=null && _attributes.size()>0)
{
ArrayList<String> keys;
synchronized(this)
{
keys=new ArrayList<String>(_attributes.keySet());
}
Iterator<String> iter=keys.iterator();
while (iter.hasNext())
{
String key=(String)iter.next();
Object value;
synchronized(this)
{
value=doPutOrRemove(key,null);
}
unbindValue(key,value);
_manager.doSessionAttributeListeners(this,key,value,null);
}
}
if (_attributes!=null)
_attributes.clear();
}
/* ------------------------------------------------------------- */
public boolean isIdChanged()
{
return _idChanged;
}
/* ------------------------------------------------------------- */
public boolean isNew() throws IllegalStateException
{
checkValid();
return _newSession;
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #setAttribute}
*/
@Deprecated
public void putValue(java.lang.String name, java.lang.Object value) throws IllegalStateException
{
setAttribute(name,value);
}
/* ------------------------------------------------------------ */
public void removeAttribute(String name)
{
setAttribute(name,null);
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #removeAttribute}
*/
@Deprecated
public void removeValue(java.lang.String name) throws IllegalStateException
{
removeAttribute(name);
}
/* ------------------------------------------------------------ */
protected Object doPutOrRemove(String name, Object value)
{
return value==null?_attributes.remove(name):_attributes.put(name,value);
}
/* ------------------------------------------------------------ */
protected Object doGet(String name)
{
return _attributes.get(name);
}
/* ------------------------------------------------------------ */
public void setAttribute(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);
}
}
/* ------------------------------------------------------------- */
public void setIdChanged(boolean changed)
{
_idChanged=changed;
}
/* ------------------------------------------------------------- */
public void setMaxInactiveInterval(int secs)
{
_maxIdleMs=(long)secs*1000;
}
/* ------------------------------------------------------------- */
@Override
public String toString()
{
return this.getClass().getName()+":"+getId()+"@"+hashCode();
}
/* ------------------------------------------------------------- */
/** If value implements HttpSessionBindingListener, call valueBound() */
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()
{
_cookieSet=_accessed;
}
/* ------------------------------------------------------------ */
public int getRequests()
{
synchronized (this)
{
return _requests;
}
}
/* ------------------------------------------------------------ */
public void setRequests(int requests)
{
synchronized (this)
{
_requests=requests;
}
}
/* ------------------------------------------------------------- */
/** If value implements HttpSessionBindingListener, call valueUnbound() */
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 = _attributes.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 = _attributes.values().iterator(); iter.hasNext();)
{
Object value = iter.next();
if (value instanceof HttpSessionActivationListener)
{
HttpSessionActivationListener listener = (HttpSessionActivationListener) value;
listener.sessionDidActivate(event);
}
}
}
}
}

View File

@ -15,24 +15,18 @@ package org.eclipse.jetty.server.session;
import static java.lang.Math.round;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@ -44,9 +38,8 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.statistic.CounterStatistic;
import org.eclipse.jetty.util.statistic.SampleStatistic;
@ -59,16 +52,29 @@ import org.eclipse.jetty.util.statistic.SampleStatistic;
* a specialised version of the Session inner class that provides an attribute
* Map.
* <p>
*
*
*/
@SuppressWarnings("deprecation")
public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
{
final static Logger __log = SessionHandler.__log;
/* ------------------------------------------------------------ */
public final static int __distantFuture=60*60*24*7*52*20;
private static final HttpSessionContext __nullSessionContext=new NullSessionContext();
static final HttpSessionContext __nullSessionContext=new HttpSessionContext()
{
public HttpSession getSession(String sessionId)
{
return null;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Enumeration getIds()
{
return Collections.enumeration(Collections.EMPTY_LIST);
}
};
private boolean _usingCookies=true;
/* ------------------------------------------------------------ */
@ -79,8 +85,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
protected boolean _httpOnly=false;
protected SessionIdManager _sessionIdManager;
protected boolean _secureCookies=false;
protected Object _sessionAttributeListeners;
protected Object _sessionListeners;
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
protected ClassLoader _loader;
protected ContextHandler.Context _context;
@ -102,27 +108,40 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
{
}
/* ------------------------------------------------------------ */
public ContextHandler.Context getContext()
{
return _context;
}
/* ------------------------------------------------------------ */
public ContextHandler getContextHandler()
{
return _context.getContextHandler();
}
/* ------------------------------------------------------------ */
public HttpCookie access(HttpSession session,boolean secure)
{
long now=System.currentTimeMillis();
Session s = ((SessionIf)session).getSession();
s.access(now);
AbstractSession s = ((SessionIf)session).getSession();
// Do we need to refresh the cookie?
if (isUsingCookies() &&
(s.isIdChanged() ||
(getMaxCookieAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
)
)
if (s.access(now))
{
HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure);
s.cookieSet();
s.setIdChanged(false);
return cookie;
// Do we need to refresh the cookie?
if (isUsingCookies() &&
(s.isIdChanged() ||
(getMaxCookieAge()>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;
}
@ -130,22 +149,22 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
public void addEventListener(EventListener listener)
{
if (listener instanceof HttpSessionAttributeListener)
_sessionAttributeListeners=LazyList.add(_sessionAttributeListeners,listener);
_sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
if (listener instanceof HttpSessionListener)
_sessionListeners=LazyList.add(_sessionListeners,listener);
_sessionListeners.add((HttpSessionListener)listener);
}
/* ------------------------------------------------------------ */
public void clearEventListeners()
{
_sessionAttributeListeners=null;
_sessionListeners=null;
_sessionAttributeListeners.clear();
_sessionListeners.clear();
}
/* ------------------------------------------------------------ */
public void complete(HttpSession session)
{
Session s = ((SessionIf)session).getSession();
AbstractSession s = ((SessionIf)session).getSession();
s.complete();
}
@ -230,20 +249,29 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
public HttpSession getHttpSession(String nodeId)
{
String cluster_id = getIdManager().getClusterId(nodeId);
String cluster_id = getSessionIdManager().getClusterId(nodeId);
Session session = getSession(cluster_id);
AbstractSession session = getSession(cluster_id);
if (session!=null && !session.getNodeId().equals(nodeId))
session.setIdChanged(true);
return session;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/**
* @return Returns the metaManager used for cross context session management
* @deprecated Use {@link #getSessionIdManager()}
*/
public SessionIdManager getIdManager()
{
return getSessionIdManager();
}
/* ------------------------------------------------------------ */
/**
* @return Returns the SessionIdManager used for cross context session management
*/
public SessionIdManager getSessionIdManager()
{
return _sessionIdManager;
}
@ -293,12 +321,12 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
* @deprecated use {@link #getIdManager()}
* @deprecated use {@link #getSessionIdManager()}
*/
@Deprecated
public SessionIdManager getMetaManager()
{
return getIdManager();
return getSessionIdManager();
}
/* ------------------------------------------------------------ */
@ -373,7 +401,11 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/**
* @deprecated Need to review if it is needed.
*/
public abstract Map getSessionMap();
@SuppressWarnings("rawtypes")
public Map getSessionMap()
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
public String getSessionPath()
@ -411,21 +443,21 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
public boolean isValid(HttpSession session)
{
Session s = ((SessionIf)session).getSession();
AbstractSession s = ((SessionIf)session).getSession();
return s.isValid();
}
/* ------------------------------------------------------------ */
public String getClusterId(HttpSession session)
{
Session s = ((SessionIf)session).getSession();
AbstractSession s = ((SessionIf)session).getSession();
return s.getClusterId();
}
/* ------------------------------------------------------------ */
public String getNodeId(HttpSession session)
{
Session s = ((SessionIf)session).getSession();
AbstractSession s = ((SessionIf)session).getSession();
return s.getNodeId();
}
@ -435,7 +467,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
*/
public HttpSession newHttpSession(HttpServletRequest request)
{
Session session=newSession(request);
AbstractSession session=newSession(request);
session.setMaxInactiveInterval(_dftMaxIdleSecs);
addSession(session,true);
return session;
@ -445,9 +477,9 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
public void removeEventListener(EventListener listener)
{
if (listener instanceof HttpSessionAttributeListener)
_sessionAttributeListeners=LazyList.remove(_sessionAttributeListeners,listener);
_sessionAttributeListeners.remove(listener);
if (listener instanceof HttpSessionListener)
_sessionListeners=LazyList.remove(_sessionListeners,listener);
_sessionListeners.remove(listener);
}
/* ------------------------------------------------------------ */
@ -480,12 +512,21 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
_httpOnly=httpOnly;
}
/* ------------------------------------------------------------ */
/**
* @param metaManager The metaManager used for cross context session management.
* @deprecated use {@link #setSessionIdManager(SessionIdManager)}
*/
public void setIdManager(SessionIdManager metaManager)
{
setSessionIdManager(metaManager);
}
/* ------------------------------------------------------------ */
/**
* @param metaManager The metaManager used for cross context session management.
*/
public void setIdManager(SessionIdManager metaManager)
public void setSessionIdManager(SessionIdManager metaManager)
{
_sessionIdManager=metaManager;
}
@ -511,12 +552,12 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
* @deprecated use {@link #setIdManager(SessionIdManager)}
* @deprecated use {@link #setSessionIdManager(SessionIdManager)}
*/
@Deprecated
public void setMetaManager(SessionIdManager metaManager)
{
setIdManager(metaManager);
setSessionIdManager(metaManager);
}
/* ------------------------------------------------------------ */
@ -591,14 +632,14 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
}
protected abstract void addSession(Session session);
protected abstract void addSession(AbstractSession session);
/* ------------------------------------------------------------ */
/**
* Add the session Registers the session with this manager and registers the
* session ID with the sessionIDManager;
*/
protected void addSession(Session session, boolean created)
protected void addSession(AbstractSession session, boolean created)
{
synchronized (_sessionIdManager)
{
@ -612,8 +653,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (int i=0; i<LazyList.size(_sessionListeners); i++)
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionCreated(event);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionCreated(event);
}
}
}
@ -624,7 +665,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
* @param idInCluster The session ID in the cluster, stripped of any worker name.
* @return A Session or null if none exists.
*/
public abstract Session getSession(String idInCluster);
public abstract AbstractSession getSession(String idInCluster);
protected abstract void invalidateSessions() throws Exception;
@ -635,7 +676,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
* @param request
* @return the new session
*/
protected abstract Session newSession(HttpServletRequest request);
protected abstract AbstractSession newSession(HttpServletRequest request);
/* ------------------------------------------------------------ */
@ -664,7 +705,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
*/
public void removeSession(HttpSession session, boolean invalidate)
{
Session s = ((SessionIf)session).getSession();
AbstractSession s = ((SessionIf)session).getSession();
removeSession(s,invalidate);
}
@ -674,7 +715,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
* {@link SessionIdManager#invalidateAll(String)} should be called.
*/
public void removeSession(Session session, boolean invalidate)
public void removeSession(AbstractSession session, boolean invalidate)
{
// Remove session from context and global maps
boolean removed = removeSession(session.getClusterId());
@ -692,8 +733,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
if (invalidate && _sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (int i=LazyList.size(_sessionListeners); i-->0;)
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionDestroyed(event);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionCreated(event);
}
}
}
@ -754,41 +795,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
{
_checkingRemoteSessionIdEncoding=remote;
}
/* ------------------------------------------------------------ */
/**
* Null returning implementation of HttpSessionContext
*
*
*/
public static class NullSessionContext implements HttpSessionContext
{
/* ------------------------------------------------------------ */
private NullSessionContext()
{
}
/* ------------------------------------------------------------ */
/**
* @deprecated From HttpSessionContext
*/
@Deprecated
public Enumeration getIds()
{
return Collections.enumeration(Collections.EMPTY_LIST);
}
/* ------------------------------------------------------------ */
/**
* @deprecated From HttpSessionContext
*/
@Deprecated
public HttpSession getSession(String id)
{
return null;
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
@ -799,496 +806,23 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
*/
public interface SessionIf extends HttpSession
{
public Session getSession();
public AbstractSession getSession();
}
/* ------------------------------------------------------------ */
/**
*
* <p>
* Implements {@link javax.servlet.http.HttpSession} from the <code>javax.servlet</code> package.
* </p>
*
*
*/
public abstract class Session implements SessionIf, Serializable
public void doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value)
{
protected final String _clusterId; // ID unique within cluster
protected final String _nodeId; // ID unique within node
protected final Map<String,Object> _attributes=new HashMap<String, Object>();
protected boolean _idChanged;
protected final long _created;
protected long _cookieSet;
protected long _accessed;
protected long _lastAccessed;
protected boolean _invalid;
protected boolean _doInvalidate;
protected long _maxIdleMs=_dftMaxIdleSecs>0?_dftMaxIdleSecs*1000:-1;
protected boolean _newSession;
protected int _requests;
if (!_sessionAttributeListeners.isEmpty())
{
HttpSessionBindingEvent event=new HttpSessionBindingEvent(session,name,old==null?value:old);
/* ------------------------------------------------------------- */
protected Session(HttpServletRequest request)
{
_newSession=true;
_created=System.currentTimeMillis();
_clusterId=_sessionIdManager.newSessionId(request,_created);
_nodeId=_sessionIdManager.getNodeId(_clusterId,request);
_accessed=_created;
_lastAccessed=_created;
_requests=1;
Log.debug("new session & id "+_nodeId+" "+_clusterId);
}
/* ------------------------------------------------------------- */
protected Session(long created, long accessed, String clusterId)
{
_created=created;
_clusterId=clusterId;
_nodeId=_sessionIdManager.getNodeId(_clusterId,null);
_accessed=accessed;
_lastAccessed=accessed;
_requests=1;
Log.debug("new session "+_nodeId+" "+_clusterId);
}
/* ------------------------------------------------------------- */
/**
* @return True is the session is invalid or passivated.
*/
protected boolean isNotAvailable()
{
return _invalid;
}
/* ------------------------------------------------------------- */
public Session getSession()
{
return this;
}
/* ------------------------------------------------------------ */
public Object getAttribute(String name)
{
synchronized (Session.this)
for (HttpSessionAttributeListener l : _sessionAttributeListeners)
{
if (isNotAvailable())
throw new IllegalStateException();
return _attributes.get(name);
}
}
/* ------------------------------------------------------------ */
public Enumeration getAttributeNames()
{
synchronized (Session.this)
{
if (isNotAvailable())
throw new IllegalStateException();
List names=_attributes==null?Collections.EMPTY_LIST:new ArrayList(_attributes.keySet());
return Collections.enumeration(names);
}
}
/* ------------------------------------------------------------- */
public long getCookieSetTime()
{
return _cookieSet;
}
/* ------------------------------------------------------------- */
public long getCreationTime() throws IllegalStateException
{
if (isNotAvailable())
throw new IllegalStateException();
return _created;
}
/* ------------------------------------------------------------ */
public String getId() throws IllegalStateException
{
return _nodeIdInSessionId?_nodeId:_clusterId;
}
/* ------------------------------------------------------------- */
protected String getNodeId()
{
return _nodeId;
}
/* ------------------------------------------------------------- */
protected String getClusterId()
{
return _clusterId;
}
/* ------------------------------------------------------------- */
public long getLastAccessedTime() throws IllegalStateException
{
if (isNotAvailable())
throw new IllegalStateException();
return _lastAccessed;
}
/* ------------------------------------------------------------- */
public int getMaxInactiveInterval()
{
if (isNotAvailable())
throw new IllegalStateException();
return (int)(_maxIdleMs/1000);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpSession#getServletContext()
*/
public ServletContext getServletContext()
{
return _context;
}
/* ------------------------------------------------------------- */
/**
* @deprecated
*/
@Deprecated
public HttpSessionContext getSessionContext() throws IllegalStateException
{
if (isNotAvailable())
throw new IllegalStateException();
return __nullSessionContext;
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #getAttribute}
*/
@Deprecated
public Object getValue(String name) throws IllegalStateException
{
return getAttribute(name);
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #getAttributeNames}
*/
@Deprecated
public String[] getValueNames() throws IllegalStateException
{
synchronized(Session.this)
{
if (isNotAvailable())
throw new IllegalStateException();
if (_attributes==null)
return new String[0];
String[] a=new String[_attributes.size()];
return (String[])_attributes.keySet().toArray(a);
}
}
/* ------------------------------------------------------------ */
protected void access(long time)
{
synchronized(Session.this)
{
if (!_invalid)
{
_newSession=false;
_lastAccessed=_accessed;
_accessed=time;
if (_maxIdleMs>0 && _lastAccessed>0 && _lastAccessed + _maxIdleMs < time)
{
invalidate();
}
else
{
_requests++;
}
}
}
}
/* ------------------------------------------------------------ */
protected void complete()
{
synchronized(Session.this)
{
_requests--;
if (_doInvalidate && _requests<=0 )
doInvalidate();
}
}
/* ------------------------------------------------------------- */
protected void timeout() throws IllegalStateException
{
// remove session from context and invalidate other sessions with same ID.
removeSession(this,true);
// Notify listeners and unbind values
synchronized (Session.this)
{
if (!_invalid)
{
if (_requests<=0)
doInvalidate();
else
_doInvalidate=true;
}
}
}
/* ------------------------------------------------------------- */
public void invalidate() throws IllegalStateException
{
// remove session from context and invalidate other sessions with same ID.
removeSession(this,true);
doInvalidate();
}
/* ------------------------------------------------------------- */
protected void doInvalidate() throws IllegalStateException
{
try
{
Log.debug("invalidate ",_clusterId);
// Notify listeners and unbind values
if (isNotAvailable())
throw new IllegalStateException();
clearAttributes();
}
finally
{
// mark as invalid
_invalid=true;
}
}
/* ------------------------------------------------------------- */
protected void clearAttributes()
{
while (_attributes!=null && _attributes.size()>0)
{
ArrayList keys;
synchronized (Session.this)
{
keys=new ArrayList(_attributes.keySet());
}
Iterator iter=keys.iterator();
while (iter.hasNext())
{
String key=(String)iter.next();
Object value;
synchronized (Session.this)
{
value=_attributes.remove(key);
}
unbindValue(key,value);
if (_sessionAttributeListeners!=null)
{
HttpSessionBindingEvent event=new HttpSessionBindingEvent(this,key,value);
for (int i=0; i<LazyList.size(_sessionAttributeListeners); i++)
((HttpSessionAttributeListener)LazyList.get(_sessionAttributeListeners,i)).attributeRemoved(event);
}
}
}
if (_attributes!=null)
_attributes.clear();
}
/* ------------------------------------------------------------- */
public boolean isIdChanged()
{
return _idChanged;
}
/* ------------------------------------------------------------- */
public boolean isNew() throws IllegalStateException
{
if (isNotAvailable())
throw new IllegalStateException();
return _newSession;
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #setAttribute}
*/
@Deprecated
public void putValue(java.lang.String name, java.lang.Object value) throws IllegalStateException
{
setAttribute(name,value);
}
/* ------------------------------------------------------------ */
public void removeAttribute(String name)
{
Object old;
synchronized(Session.this)
{
if (isNotAvailable())
throw new IllegalStateException();
if (_attributes==null)
return;
old=_attributes.remove(name);
}
if (old!=null)
{
unbindValue(name,old);
if (_sessionAttributeListeners!=null)
{
HttpSessionBindingEvent event=new HttpSessionBindingEvent(this,name,old);
for (int i=0; i<LazyList.size(_sessionAttributeListeners); i++)
((HttpSessionAttributeListener)LazyList.get(_sessionAttributeListeners,i)).attributeRemoved(event);
}
}
}
/* ------------------------------------------------------------- */
/**
* @deprecated As of Version 2.2, this method is replaced by
* {@link #removeAttribute}
*/
@Deprecated
public void removeValue(java.lang.String name) throws IllegalStateException
{
removeAttribute(name);
}
/* ------------------------------------------------------------ */
public void setAttribute(String name, Object value)
{
Object old_value=null;
synchronized (Session.this)
{
if (value==null)
{
removeAttribute(name);
return;
}
if (isNotAvailable())
throw new IllegalStateException();
old_value=_attributes.put(name,value);
}
if (old_value==null || !value.equals(old_value))
{
unbindValue(name,old_value);
bindValue(name,value);
if (_sessionAttributeListeners!=null)
{
HttpSessionBindingEvent event=new HttpSessionBindingEvent(this,name,old_value==null?value:old_value);
for (int i=0; i<LazyList.size(_sessionAttributeListeners); i++)
{
HttpSessionAttributeListener l=(HttpSessionAttributeListener)LazyList.get(_sessionAttributeListeners,i);
if (old_value==null)
l.attributeAdded(event);
else
l.attributeReplaced(event);
}
}
}
}
/* ------------------------------------------------------------- */
public void setIdChanged(boolean changed)
{
_idChanged=changed;
}
/* ------------------------------------------------------------- */
public void setMaxInactiveInterval(int secs)
{
_maxIdleMs=(long)secs*1000;
}
/* ------------------------------------------------------------- */
@Override
public String toString()
{
return this.getClass().getName()+":"+getId()+"@"+hashCode();
}
/* ------------------------------------------------------------- */
/** If value implements HttpSessionBindingListener, call valueBound() */
protected void bindValue(java.lang.String name, Object value)
{
if (value!=null&&value instanceof HttpSessionBindingListener)
((HttpSessionBindingListener)value).valueBound(new HttpSessionBindingEvent(this,name));
}
/* ------------------------------------------------------------ */
protected boolean isValid()
{
return !_invalid;
}
/* ------------------------------------------------------------- */
protected void cookieSet()
{
_cookieSet=_accessed;
}
/* ------------------------------------------------------------- */
/** If value implements HttpSessionBindingListener, call valueUnbound() */
protected void unbindValue(java.lang.String name, Object value)
{
if (value!=null&&value instanceof HttpSessionBindingListener)
((HttpSessionBindingListener)value).valueUnbound(new HttpSessionBindingEvent(this,name));
}
/* ------------------------------------------------------------- */
protected void willPassivate()
{
synchronized(Session.this)
{
HttpSessionEvent event = new HttpSessionEvent(this);
for (Iterator iter = _attributes.values().iterator(); iter.hasNext();)
{
Object value = iter.next();
if (value instanceof HttpSessionActivationListener)
{
HttpSessionActivationListener listener = (HttpSessionActivationListener) value;
listener.sessionWillPassivate(event);
}
}
}
}
/* ------------------------------------------------------------- */
protected void didActivate()
{
synchronized(Session.this)
{
HttpSessionEvent event = new HttpSessionEvent(this);
for (Iterator iter = _attributes.values().iterator(); iter.hasNext();)
{
Object value = iter.next();
if (value instanceof HttpSessionActivationListener)
{
HttpSessionActivationListener listener = (HttpSessionActivationListener) value;
listener.sessionDidActivate(event);
}
}
if (old==null)
l.attributeAdded(event);
else if (value==null)
l.attributeRemoved(event);
else
l.attributeReplaced(event);
}
}
}

View File

@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.session.AbstractSessionManager.Session;
import org.eclipse.jetty.util.MultiMap;
/* ------------------------------------------------------------ */
@ -183,7 +182,7 @@ public class HashSessionIdManager extends AbstractSessionIdManager
{
for (WeakReference<HttpSession> ref: sessions)
{
Session session=(Session)ref.get();
AbstractSession session=(AbstractSession)ref.get();
if (session!=null && session.isValid())
session.invalidate();
}

View File

@ -14,16 +14,11 @@
package org.eclipse.jetty.server.session;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@ -37,8 +32,8 @@ import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
@ -53,16 +48,18 @@ import org.eclipse.jetty.util.log.Log;
*/
public class HashSessionManager extends AbstractSessionManager
{
final static Logger __log = SessionHandler.__log;
protected final ConcurrentMap<String,HashedSession> _sessions=new ConcurrentHashMap<String,HashedSession>();
private static int __id;
private Timer _timer;
private boolean _timerStop=false;
private TimerTask _task;
private int _scavengePeriodMs=30000;
private int _savePeriodMs=0; //don't do period saves by default
private int _idleSavePeriodMs = 0; // don't idle save sessions by default.
int _scavengePeriodMs=30000;
int _savePeriodMs=0; //don't do period saves by default
int _idleSavePeriodMs = 0; // don't idle save sessions by default.
private TimerTask _saveTask;
private File _storeDir;
File _storeDir;
private boolean _lazyLoad=false;
private volatile boolean _sessionsLoaded=false;
@ -142,24 +139,16 @@ public class HashSessionManager extends AbstractSessionManager
return _scavengePeriodMs/1000;
}
/* ------------------------------------------------------------ */
@Override
public Map getSessionMap()
{
return Collections.unmodifiableMap(_sessions);
}
/* ------------------------------------------------------------ */
@Override
public int getSessions()
{
int sessions=super.getSessions();
if (Log.isDebugEnabled())
if (__log.isDebugEnabled())
{
if (_sessions.size()!=sessions)
Log.warn("sessions: "+_sessions.size()+"!="+sessions);
__log.warn("sessions: "+_sessions.size()+"!="+sessions);
}
return sessions;
}
@ -229,7 +218,7 @@ public class HashSessionManager extends AbstractSessionManager
}
catch (Exception e)
{
Log.warn(e);
__log.warn(e);
}
}
};
@ -310,13 +299,13 @@ public class HashSessionManager extends AbstractSessionManager
for (Iterator<HashedSession> i=_sessions.values().iterator(); i.hasNext();)
{
HashedSession session=i.next();
long idleTime=session._maxIdleMs;
if (idleTime>0&&session._accessed+idleTime<now)
long idleTime=session.getMaxInactiveInterval()*1000;
if (idleTime>0&&session.getAccessed()+idleTime<now)
{
// Found a stale session, add it to the list
session.timeout();
}
else if (_idleSavePeriodMs>0&&session._accessed+_idleSavePeriodMs<now)
else if (_idleSavePeriodMs>0&&session.getAccessed()+_idleSavePeriodMs<now)
{
session.idle();
}
@ -327,7 +316,7 @@ public class HashSessionManager extends AbstractSessionManager
if (t instanceof ThreadDeath)
throw ((ThreadDeath)t);
else
Log.warn("Problem scavenging sessions", t);
__log.warn("Problem scavenging sessions", t);
}
finally
{
@ -337,7 +326,7 @@ public class HashSessionManager extends AbstractSessionManager
/* ------------------------------------------------------------ */
@Override
protected void addSession(AbstractSessionManager.Session session)
protected void addSession(AbstractSession session)
{
if (isRunning())
_sessions.put(session.getClusterId(),(HashedSession)session);
@ -345,7 +334,7 @@ public class HashSessionManager extends AbstractSessionManager
/* ------------------------------------------------------------ */
@Override
public AbstractSessionManager.Session getSession(String idInCluster)
public AbstractSession getSession(String idInCluster)
{
if ( _lazyLoad && !_sessionsLoaded)
{
@ -355,7 +344,7 @@ public class HashSessionManager extends AbstractSessionManager
}
catch(Exception e)
{
Log.warn(e);
__log.warn(e);
}
}
@ -408,15 +397,15 @@ public class HashSessionManager extends AbstractSessionManager
/* ------------------------------------------------------------ */
@Override
protected AbstractSessionManager.Session newSession(HttpServletRequest request)
protected AbstractSession newSession(HttpServletRequest request)
{
return new HashedSession(request);
return new HashedSession(this, request);
}
/* ------------------------------------------------------------ */
protected AbstractSessionManager.Session newSession(long created, long accessed, String clusterId)
protected AbstractSession newSession(long created, long accessed, String clusterId)
{
return new HashedSession(created,accessed, clusterId);
return new HashedSession(this, created,accessed, clusterId);
}
/* ------------------------------------------------------------ */
@ -462,7 +451,7 @@ public class HashSessionManager extends AbstractSessionManager
if (!_storeDir.canRead())
{
Log.warn ("Unable to restore Sessions: Cannot read from Session storage directory "+_storeDir.getAbsolutePath());
__log.warn ("Unable to restore Sessions: Cannot read from Session storage directory "+_storeDir.getAbsolutePath());
return;
}
@ -492,7 +481,7 @@ public class HashSessionManager extends AbstractSessionManager
}
catch (Exception e)
{
Log.warn("Problem restoring session "+idInCuster, e);
__log.warn("Problem restoring session "+idInCuster, e);
}
return null;
}
@ -507,7 +496,7 @@ public class HashSessionManager extends AbstractSessionManager
if (!_storeDir.canWrite())
{
Log.warn ("Unable to save Sessions: Session persistence storage directory "+_storeDir.getAbsolutePath()+ " is not writeable");
__log.warn ("Unable to save Sessions: Session persistence storage directory "+_storeDir.getAbsolutePath()+ " is not writeable");
return;
}
@ -525,23 +514,13 @@ public class HashSessionManager extends AbstractSessionManager
DataInputStream in = new DataInputStream(is);
String clusterId = in.readUTF();
String nodeId = in.readUTF();
boolean idChanged = in.readBoolean();
long created = in.readLong();
long cookieSet = in.readLong();
long accessed = in.readLong();
long lastAccessed = in.readLong();
//boolean invalid = in.readBoolean();
//boolean invalidate = in.readBoolean();
//long maxIdle = in.readLong();
//boolean isNew = in.readBoolean();
int requests = in.readInt();
if (session == null)
session = (HashedSession)newSession(created, System.currentTimeMillis(), clusterId);
session._cookieSet = cookieSet;
session._lastAccessed = lastAccessed;
session = (HashedSession)newSession(created, accessed, clusterId);
session.setRequests(requests);
int size = in.readInt();
if (size>0)
{
@ -560,228 +539,6 @@ public class HashSessionManager extends AbstractSessionManager
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected class HashedSession extends Session
{
/* ------------------------------------------------------------ */
private static final long serialVersionUID=-2134521374206116367L;
/** Whether the session has been saved because it has been deemed idle;
* in which case its attribute map will have been saved and cleared. */
private transient boolean _idled = false;
/** Whether there has already been an attempt to save this session
* which has failed. If there has, there will be no more save attempts
* for this session. This is to stop the logs being flooded with errors
* due to serialization failures that are most likely caused by user
* data stored in the session that is not serializable. */
private transient boolean _saveFailed = false;
/* ------------------------------------------------------------- */
protected HashedSession(HttpServletRequest request)
{
super(request);
}
/* ------------------------------------------------------------- */
protected HashedSession(long created, long accessed, String clusterId)
{
super(created, accessed, clusterId);
}
/* ------------------------------------------------------------- */
protected boolean isNotAvailable()
{
if (_idleSavePeriodMs!=0)
deIdle();
return _invalid;
}
/* ------------------------------------------------------------- */
@Override
public void setMaxInactiveInterval(int secs)
{
super.setMaxInactiveInterval(secs);
if (_maxIdleMs>0&&(_maxIdleMs/10)<_scavengePeriodMs)
HashSessionManager.this.setScavengePeriod((secs+9)/10);
}
/* ------------------------------------------------------------ */
@Override
protected void doInvalidate()
throws IllegalStateException
{
super.doInvalidate();
// Remove from the disk
if (_storeDir!=null && getId()!=null)
{
String id=getId();
File f = new File(_storeDir, id);
f.delete();
}
}
/* ------------------------------------------------------------ */
private synchronized void save(boolean reactivate)
{
// 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);
File file = null;
FileOutputStream fos = null;
try
{
file = new File(_storeDir, super.getId());
if (file.exists())
file.delete();
file.createNewFile();
fos = new FileOutputStream(file);
willPassivate();
save(fos);
if (reactivate)
didActivate();
else
clearAttributes();
}
catch (Exception e)
{
saveFailed(); // We won't try again for this session
Log.warn("Problem saving session " + super.getId(), e);
if (fos != null)
{
// Must not leave the file open if the saving failed
IO.close(fos);
// No point keeping the file if we didn't save the whole session
file.delete();
_idled=false; // assume problem was before _values.clear();
}
}
}
}
/* ------------------------------------------------------------ */
public synchronized void save(OutputStream os) throws IOException
{
DataOutputStream out = new DataOutputStream(os);
out.writeUTF(_clusterId);
out.writeUTF(_nodeId);
out.writeBoolean(_idChanged);
out.writeLong( _created);
out.writeLong(_cookieSet);
out.writeLong(_accessed);
out.writeLong(_lastAccessed);
/* 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.writeLong(_maxIdleMs);
//out.writeBoolean( _newSession);
out.writeInt(_requests);
if (_attributes != null)
{
out.writeInt(_attributes.size());
ObjectOutputStream oos = new ObjectOutputStream(out);
for (Map.Entry<String,Object> entry: _attributes.entrySet())
{
oos.writeUTF(entry.getKey());
oos.writeObject(entry.getValue());
}
oos.close();
}
else
{
out.writeInt(0);
out.close();
}
}
/* ------------------------------------------------------------ */
public synchronized void deIdle()
{
if (isIdled())
{
// Access now to prevent race with idling period
access(System.currentTimeMillis());
if (Log.isDebugEnabled())
{
Log.debug("Deidling " + super.getId());
}
FileInputStream fis = null;
try
{
File file = new File(_storeDir, super.getId());
if (!file.exists() || !file.canRead())
throw new FileNotFoundException(file.getName());
fis = new FileInputStream(file);
_idled = false;
restoreSession(fis, this);
didActivate();
// If we are doing period saves, then there is no point deleting at this point
if (_savePeriodMs == 0)
file.delete();
}
catch (Exception e)
{
Log.warn("Problem deidling session " + super.getId(), e);
IO.close(fis);
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.
*/
public synchronized void idle()
{
save(false);
}
/* ------------------------------------------------------------ */
public boolean isIdled()
{
return _idled;
}
/* ------------------------------------------------------------ */
public boolean isSaveFailed()
{
return _saveFailed;
}
/* ------------------------------------------------------------ */
public void saveFailed()
{
_saveFailed = true;
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected class ClassLoadingObjectInputStream extends ObjectInputStream

View File

@ -0,0 +1,227 @@
package org.eclipse.jetty.server.session;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
class HashedSession extends AbstractSession
{
private final HashSessionManager _hashSessionManager;
/** Whether the session has been saved because it has been deemed idle;
* in which case its attribute map will have been saved and cleared. */
private transient boolean _idled = false;
/** Whether there has already been an attempt to save this session
* which has failed. If there has, there will be no more save attempts
* for this session. This is to stop the logs being flooded with errors
* due to serialization failures that are most likely caused by user
* data stored in the session that is not serializable. */
private transient boolean _saveFailed = false;
/* ------------------------------------------------------------- */
protected HashedSession(HashSessionManager hashSessionManager, HttpServletRequest request)
{
super(hashSessionManager,request);
_hashSessionManager = hashSessionManager;
}
/* ------------------------------------------------------------- */
protected HashedSession(HashSessionManager hashSessionManager, long created, long accessed, String clusterId)
{
super(hashSessionManager,created, accessed, clusterId);
_hashSessionManager = hashSessionManager;
}
/* ------------------------------------------------------------- */
protected void checkValid()
{
if (_hashSessionManager._idleSavePeriodMs!=0)
deIdle();
super.checkValid();
}
/* ------------------------------------------------------------- */
@Override
public void setMaxInactiveInterval(int secs)
{
super.setMaxInactiveInterval(secs);
if (getMaxInactiveInterval()>0&&(getMaxInactiveInterval()*1000/10)<_hashSessionManager._scavengePeriodMs)
_hashSessionManager.setScavengePeriod((secs+9)/10);
}
/* ------------------------------------------------------------ */
@Override
protected void doInvalidate()
throws IllegalStateException
{
super.doInvalidate();
// Remove from the disk
if (_hashSessionManager._storeDir!=null && getId()!=null)
{
String id=getId();
File f = new File(_hashSessionManager._storeDir, id);
f.delete();
}
}
/* ------------------------------------------------------------ */
synchronized void save(boolean reactivate)
{
// 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);
File file = null;
FileOutputStream fos = null;
try
{
file = new File(_hashSessionManager._storeDir, super.getId());
if (file.exists())
file.delete();
file.createNewFile();
fos = new FileOutputStream(file);
willPassivate();
save(fos);
if (reactivate)
didActivate();
else
clearAttributes();
}
catch (Exception e)
{
saveFailed(); // We won't try again for this session
Log.warn("Problem saving session " + super.getId(), e);
if (fos != null)
{
// Must not leave the file open if the saving failed
IO.close(fos);
// No point keeping the file if we didn't save the whole session
file.delete();
_idled=false; // assume problem was before _values.clear();
}
}
}
}
/* ------------------------------------------------------------ */
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.writeLong(_maxIdleMs);
//out.writeBoolean( _newSession);
out.writeInt(getRequests());
out.writeInt(getAttributes());
ObjectOutputStream oos = new ObjectOutputStream(out);
Enumeration<String> e=getAttributeNames();
while(e.hasMoreElements())
{
String key=e.nextElement();
oos.writeUTF(key);
oos.writeObject(doGet(key));
}
oos.close();
}
/* ------------------------------------------------------------ */
public synchronized void deIdle()
{
if (isIdled())
{
// Access now to prevent race with idling period
access(System.currentTimeMillis());
if (Log.isDebugEnabled())
{
Log.debug("Deidling " + 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);
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)
{
Log.warn("Problem deidling session " + super.getId(), e);
IO.close(fis);
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.
*/
public synchronized void idle()
{
save(false);
}
/* ------------------------------------------------------------ */
public synchronized boolean isIdled()
{
return _idled;
}
/* ------------------------------------------------------------ */
public synchronized boolean isSaveFailed()
{
return _saveFailed;
}
/* ------------------------------------------------------------ */
public synchronized void saveFailed()
{
_saveFailed = true;
}
}

View File

@ -40,6 +40,7 @@ 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;
@ -52,7 +53,9 @@ import org.eclipse.jetty.util.log.Log;
*/
public class JDBCSessionIdManager extends AbstractSessionIdManager
{
protected final HashSet<String> _sessionIds = new HashSet();
final static Logger __log = SessionHandler.__log;
protected final HashSet<String> _sessionIds = new HashSet<String>();
protected Server _server;
protected String _driverClassName;
protected String _connectionUrl;
@ -104,7 +107,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
throws SQLException
{
_dbName = dbMeta.getDatabaseProductName().toLowerCase();
Log.debug ("Using database "+_dbName);
__log.debug ("Using database "+_dbName);
_isLower = dbMeta.storesLowerCaseIdentifiers();
_isUpper = dbMeta.storesUpperCaseIdentifiers();
}
@ -228,7 +231,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
if ((System.currentTimeMillis()%2) == 0)
_scavengeIntervalMs += tenPercent;
if (Log.isDebugEnabled()) Log.debug("Scavenging every "+_scavengeIntervalMs+" ms");
if (__log.isDebugEnabled()) __log.debug("Scavenging every "+_scavengeIntervalMs+" ms");
if (_timer!=null && (period!=old_period || _task==null))
{
synchronized (this)
@ -269,7 +272,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
}
catch (Exception e)
{
Log.warn("Problem storing session id="+id, e);
__log.warn("Problem storing session id="+id, e);
}
}
}
@ -292,8 +295,8 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
synchronized (_sessionIds)
{
if (Log.isDebugEnabled())
Log.debug("Removing session id="+id);
if (__log.isDebugEnabled())
__log.debug("Removing session id="+id);
try
{
_sessionIds.remove(id);
@ -301,7 +304,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
}
catch (Exception e)
{
Log.warn("Problem removing session id="+id, e);
__log.warn("Problem removing session id="+id, e);
}
}
@ -356,7 +359,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
}
catch (Exception e)
{
Log.warn("Problem checking inUse for id="+clusterId, e);
__log.warn("Problem checking inUse for id="+clusterId, e);
return false;
}
}
@ -407,13 +410,13 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
initializeDatabase();
prepareTables();
super.doStart();
if (Log.isDebugEnabled()) Log.debug("Scavenging interval = "+getScavengeInterval()+" sec");
if (__log.isDebugEnabled()) __log.debug("Scavenging interval = "+getScavengeInterval()+" sec");
_timer=new Timer("JDBCSessionScavenger", true);
setScavengeInterval(getScavengeInterval());
}
catch (Exception e)
{
Log.warn("Problem initialising JettySessionIds table", e);
__log.warn("Problem initialising JettySessionIds table", e);
}
}
@ -650,7 +653,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
List expiredSessionIds = new ArrayList();
try
{
if (Log.isDebugEnabled()) Log.debug("Scavenge sweep started at "+System.currentTimeMillis());
if (__log.isDebugEnabled()) __log.debug("Scavenge sweep started at "+System.currentTimeMillis());
if (_lastScavengeTime > 0)
{
connection = getConnection();
@ -659,7 +662,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
PreparedStatement statement = connection.prepareStatement(_selectExpiredSessions);
long lowerBound = (_lastScavengeTime - _scavengeIntervalMs);
long upperBound = _lastScavengeTime;
if (Log.isDebugEnabled()) Log.debug (" Searching for sessions expired between "+lowerBound + " and "+upperBound);
if (__log.isDebugEnabled()) __log.debug (" Searching for sessions expired between "+lowerBound + " and "+upperBound);
statement.setLong(1, lowerBound);
statement.setLong(2, upperBound);
@ -668,7 +671,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
{
String sessionId = result.getString("sessionId");
expiredSessionIds.add(sessionId);
if (Log.isDebugEnabled()) Log.debug (" Found expired sessionId="+sessionId);
if (__log.isDebugEnabled()) __log.debug (" Found expired sessionId="+sessionId);
}
//tell the SessionManagers to expire any sessions with a matching sessionId in memory
@ -691,7 +694,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
upperBound = _lastScavengeTime - (2 * _scavengeIntervalMs);
if (upperBound > 0)
{
if (Log.isDebugEnabled()) Log.debug("Deleting old expired sessions expired before "+upperBound);
if (__log.isDebugEnabled()) __log.debug("Deleting old expired sessions expired before "+upperBound);
statement = connection.prepareStatement(_deleteOldExpiredSessions);
statement.setLong(1, upperBound);
statement.executeUpdate();
@ -700,12 +703,12 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
}
catch (Exception e)
{
Log.warn("Problem selecting expired sessions", e);
__log.warn("Problem selecting expired sessions", e);
}
finally
{
_lastScavengeTime=System.currentTimeMillis();
if (Log.isDebugEnabled()) Log.debug("Scavenge sweep ended at "+_lastScavengeTime);
if (__log.isDebugEnabled()) __log.debug("Scavenge sweep ended at "+_lastScavengeTime);
if (connection != null)
{
try
@ -714,7 +717,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
}
catch (SQLException e)
{
Log.warn(e);
__log.warn(e);
}
}
}

View File

@ -105,7 +105,7 @@ public class JDBCSessionManager extends AbstractSessionManager
_created=System.currentTimeMillis();
_accessed = _created;
_attributes = new HashMap<String,Object>();
_lastNode = getIdManager().getWorkerName();
_lastNode = getSessionIdManager().getWorkerName();
}
public SessionData (String sessionId,Map<String,Object> attributes)
@ -114,7 +114,7 @@ public class JDBCSessionManager extends AbstractSessionManager
_created=System.currentTimeMillis();
_accessed = _created;
_attributes = attributes;
_lastNode = getIdManager().getWorkerName();
_lastNode = getSessionIdManager().getWorkerName();
}
public synchronized String getId ()
@ -260,7 +260,7 @@ public class JDBCSessionManager extends AbstractSessionManager
*
* Session instance in memory of this node.
*/
public class Session extends AbstractSessionManager.Session
public class Session extends AbstractSession
{
private static final long serialVersionUID = 5208464051134226143L;
private final SessionData _data;
@ -273,13 +273,14 @@ public class JDBCSessionManager extends AbstractSessionManager
*/
protected Session (HttpServletRequest request)
{
super(request);
_data = new SessionData(_clusterId,_attributes);
super(JDBCSessionManager.this,request);
_data = new SessionData(getClusterId(),_jdbcAttributes);
if (_dftMaxIdleSecs>0)
_data.setMaxIdleMs(_dftMaxIdleSecs*1000);
_data.setCanonicalContext(canonicalize(_context.getContextPath()));
_data.setVirtualHost(getVirtualHost(_context));
_data.setExpiryTime(_maxIdleMs < 0 ? 0 : (System.currentTimeMillis() + _maxIdleMs));
int maxInterval=getMaxInactiveInterval();
_data.setExpiryTime(maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000));
}
/**
@ -288,12 +289,12 @@ public class JDBCSessionManager extends AbstractSessionManager
*/
protected Session (long accessed, SessionData data)
{
super(data.getCreated(), accessed, data.getId());
super(JDBCSessionManager.this,data.getCreated(), accessed, data.getId());
_data=data;
if (_dftMaxIdleSecs>0)
_data.setMaxIdleMs(_dftMaxIdleSecs*1000);
_attributes.putAll(_data.getAttributeMap());
_data.setAttributeMap(_attributes);
_jdbcAttributes.putAll(_data.getAttributeMap());
_data.setAttributeMap(_jdbcAttributes);
}
@Override
@ -320,20 +321,26 @@ public class JDBCSessionManager extends AbstractSessionManager
* 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.AbstractSessionManager.Session#access(long)
* @see org.eclipse.jetty.server.session.AbstractSession#access(long)
*/
@Override
protected void access(long time)
protected boolean access(long time)
{
super.access(time);
_data.setLastAccessed(_data.getAccessed());
_data.setAccessed(time);
_data.setExpiryTime(_maxIdleMs < 0 ? 0 : (time + _maxIdleMs));
if (super.access(time))
{
_data.setLastAccessed(_data.getAccessed());
_data.setAccessed(time);
int maxInterval=getMaxInactiveInterval();
_data.setExpiryTime(maxInterval <= 0 ? 0 : (time + maxInterval*1000));
return true;
}
return false;
}
/**
* Exit from session
* @see org.eclipse.jetty.server.session.AbstractSessionManager.Session#complete()
* @see org.eclipse.jetty.server.session.AbstractSession#complete()
*/
@Override
protected void complete()
@ -504,7 +511,7 @@ public class JDBCSessionManager extends AbstractSessionManager
" lastSaved="+(session==null?0:session._data._lastSaved)+
" interval="+(_saveIntervalSec * 1000)+
" lastNode="+session._data.getLastNode()+
" thisNode="+getIdManager().getWorkerName()+
" thisNode="+getSessionIdManager().getWorkerName()+
" difference="+(now - session._data._lastSaved));
}
@ -526,13 +533,13 @@ public class JDBCSessionManager extends AbstractSessionManager
if (data != null)
{
if (!data.getLastNode().equals(getIdManager().getWorkerName()) || session==null)
if (!data.getLastNode().equals(getSessionIdManager().getWorkerName()) || session==null)
{
//if the session has no expiry, or it is not already expired
if (data._expiryTime <= 0 || data._expiryTime > now)
{
Log.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getIdManager().getWorkerName());
data.setLastNode(getIdManager().getWorkerName());
Log.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
data.setLastNode(getSessionIdManager().getWorkerName());
//session last used on a different node, or we don't have it in memory
session = new Session(now,data);
_sessions.put(idInCluster, session);
@ -565,17 +572,6 @@ public class JDBCSessionManager extends AbstractSessionManager
}
}
}
/**
* Get all the sessions as a map of id to Session.
*/
@Override
public Map getSessionMap()
{
return Collections.unmodifiableMap(_sessions);
}
/**
* Get the number of sessions.
@ -686,10 +682,10 @@ public class JDBCSessionManager extends AbstractSessionManager
/**
* 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.AbstractSessionManager.Session)
* @see org.eclipse.jetty.server.session.AbstractSessionManager#addSession(org.eclipse.jetty.server.session.AbstractSessionManager.AbstractSession)
*/
@Override
protected void addSession(AbstractSessionManager.Session session)
protected void addSession(AbstractSession session)
{
if (session==null)
return;
@ -720,7 +716,7 @@ public class JDBCSessionManager extends AbstractSessionManager
* @see org.eclipse.jetty.server.session.AbstractSessionManager#newSession(javax.servlet.http.HttpServletRequest)
*/
@Override
protected AbstractSessionManager.Session newSession(HttpServletRequest request)
protected AbstractSession newSession(HttpServletRequest request)
{
return new Session(request);
}
@ -732,7 +728,7 @@ public class JDBCSessionManager extends AbstractSessionManager
* {@link SessionIdManager#invalidateAll(String)} should be called.
*/
@Override
public void removeSession(AbstractSessionManager.Session session, boolean invalidate)
public void removeSession(AbstractSession session, boolean invalidate)
{
// Remove session from context and global maps
boolean removed = false;
@ -755,11 +751,11 @@ public class JDBCSessionManager extends AbstractSessionManager
if (invalidate)
_sessionIdManager.invalidateAll(session.getClusterId());
if (invalidate && _sessionListeners!=null)
if (invalidate && !_sessionListeners.isEmpty())
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (int i=LazyList.size(_sessionListeners); i-->0;)
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionDestroyed(event);
for (HttpSessionListener l : _sessionListeners)
l.sessionDestroyed(event);
}
if (!invalidate)
{
@ -883,7 +879,7 @@ public class JDBCSessionManager extends AbstractSessionManager
data.setCanonicalContext(result.getString("contextPath"));
data.setVirtualHost(result.getString("virtualHost"));
InputStream is = ((JDBCSessionIdManager)getIdManager())._dbAdaptor.getBlobInputStream(result, "map");
InputStream is = ((JDBCSessionIdManager)getSessionIdManager())._dbAdaptor.getBlobInputStream(result, "map");
ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream (is);
Object o = ois.readObject();
data.setAttributeMap((Map<String,Object>)o);
@ -946,7 +942,7 @@ public class JDBCSessionManager extends AbstractSessionManager
statement.setString(2, data.getId()); //session id
statement.setString(3, data.getCanonicalContext()); //context path
statement.setString(4, data.getVirtualHost()); //first vhost
statement.setString(5, getIdManager().getWorkerName());//my node id
statement.setString(5, getSessionIdManager().getWorkerName());//my node id
statement.setLong(6, data.getAccessed());//accessTime
statement.setLong(7, data.getLastAccessed()); //lastAccessTime
statement.setLong(8, data.getCreated()); //time created
@ -997,7 +993,7 @@ public class JDBCSessionManager extends AbstractSessionManager
long now = System.currentTimeMillis();
connection.setAutoCommit(true);
statement = connection.prepareStatement(__updateSession);
statement.setString(1, getIdManager().getWorkerName());//my node id
statement.setString(1, getSessionIdManager().getWorkerName());//my node id
statement.setLong(2, data.getAccessed());//accessTime
statement.setLong(3, data.getLastAccessed()); //lastAccessTime
statement.setLong(4, now); //last saved time
@ -1034,7 +1030,7 @@ public class JDBCSessionManager extends AbstractSessionManager
protected void updateSessionNode (SessionData data)
throws Exception
{
String nodeId = getIdManager().getWorkerName();
String nodeId = getSessionIdManager().getWorkerName();
Connection connection = getConnection();
PreparedStatement statement = null;
try
@ -1071,7 +1067,7 @@ public class JDBCSessionManager extends AbstractSessionManager
long now = System.currentTimeMillis();
connection.setAutoCommit(true);
statement = connection.prepareStatement(__updateSessionAccessTime);
statement.setString(1, getIdManager().getWorkerName());
statement.setString(1, getSessionIdManager().getWorkerName());
statement.setLong(2, data.getAccessed());
statement.setLong(3, data.getLastAccessed());
statement.setLong(4, now);
@ -1131,7 +1127,7 @@ public class JDBCSessionManager extends AbstractSessionManager
private Connection getConnection ()
throws SQLException
{
return ((JDBCSessionIdManager)getIdManager()).getConnection();
return ((JDBCSessionIdManager)getSessionIdManager()).getConnection();
}
/**

View File

@ -29,12 +29,15 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.server.handler.ScopedHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** SessionHandler.
*/
public class SessionHandler extends ScopedHandler
{
final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session");
/* -------------------------------------------------------------- */
private SessionManager _sessionManager;
@ -133,11 +136,9 @@ public class SessionHandler extends ScopedHandler
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
setRequestedId(baseRequest,request);
SessionManager old_session_manager=null;
HttpSession old_session=null;
HttpSession access=null;
try
{
old_session_manager = baseRequest.getSessionManager();
@ -148,6 +149,7 @@ public class SessionHandler extends ScopedHandler
// new session context
baseRequest.setSessionManager(_sessionManager);
baseRequest.setSession(null);
checkRequestedSessionId(baseRequest,request);
}
// access any existing session
@ -159,6 +161,7 @@ public class SessionHandler extends ScopedHandler
{
if(session!=old_session)
{
access=session;
HttpCookie cookie = _sessionManager.access(session,request.isSecure());
if (cookie!=null ) // Handle changed ID or max-age refresh
baseRequest.getResponse().addCookie(cookie);
@ -172,10 +175,10 @@ public class SessionHandler extends ScopedHandler
}
}
if(Log.isDebugEnabled())
if(__log.isDebugEnabled())
{
Log.debug("sessionManager="+_sessionManager);
Log.debug("session="+session);
__log.debug("sessionManager="+_sessionManager);
__log.debug("session="+session);
}
// start manual inline of nextScope(target,baseRequest,request,response);
@ -190,20 +193,19 @@ public class SessionHandler extends ScopedHandler
}
finally
{
HttpSession session=request.getSession(false);
if (old_session_manager != _sessionManager)
if (access!=null)
_sessionManager.complete(access);
else
{
//leaving context, free up the session
if (session!=null)
HttpSession session = baseRequest.getSession(false);
if (session!=null && old_session==null)
_sessionManager.complete(session);
// Leave last session in place
if (old_session_manager!=null )
{
baseRequest.setSessionManager(old_session_manager);
baseRequest.setSession(old_session);
}
}
if (old_session_manager!=null && old_session_manager != _sessionManager)
{
baseRequest.setSessionManager(old_session_manager);
baseRequest.setSession(old_session);
}
}
}
@ -231,13 +233,22 @@ public class SessionHandler extends ScopedHandler
* @param baseRequest
* @param request
*/
protected void setRequestedId(Request baseRequest, HttpServletRequest request)
protected void checkRequestedSessionId(Request baseRequest, HttpServletRequest request)
{
String requested_session_id=request.getRequestedSessionId();
if (!DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()) || requested_session_id!=null)
SessionManager sessionManager = getSessionManager();
if (requested_session_id!=null && sessionManager!=null)
{
HttpSession session=sessionManager.getHttpSession(requested_session_id);
if (session!=null && sessionManager.isValid(session))
baseRequest.setSession(session);
return;
}
else if (!DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
return;
SessionManager sessionManager = getSessionManager();
boolean requested_session_id_from_cookie=false;
HttpSession session=null;
@ -251,22 +262,13 @@ public class SessionHandler extends ScopedHandler
{
if (sessionManager.getSessionCookie().equalsIgnoreCase(cookies[i].getName()))
{
if (requested_session_id!=null)
{
// Multiple jsessionid cookies. Probably due to
// multiple paths and/or domains. Pick the first
// known session or the last defined cookie.
if (sessionManager.getHttpSession(requested_session_id)!=null)
break;
}
requested_session_id=cookies[i].getValue();
requested_session_id_from_cookie = true;
if(Log.isDebugEnabled())Log.debug("Got Session ID "+requested_session_id+" from cookie");
if(__log.isDebugEnabled())__log.debug("Got Session ID "+requested_session_id+" from cookie");
session=sessionManager.getHttpSession(requested_session_id);
if (session!=null)
baseRequest.setSession(session);
if (session!=null && sessionManager.isValid(session))
break;
}
}
}
@ -294,14 +296,17 @@ public class SessionHandler extends ScopedHandler
requested_session_id = uri.substring(s,i);
requested_session_id_from_cookie = false;
if(Log.isDebugEnabled())
Log.debug("Got Session ID "+requested_session_id+" from URL");
session=sessionManager.getHttpSession(requested_session_id);
if(__log.isDebugEnabled())
__log.debug("Got Session ID "+requested_session_id+" from URL");
}
}
}
baseRequest.setRequestedSessionId(requested_session_id);
baseRequest.setRequestedSessionIdFromCookie(requested_session_id!=null && requested_session_id_from_cookie);
baseRequest.setRequestedSessionIdFromCookie(requested_session_id!=null && requested_session_id_from_cookie);
if (session!=null && sessionManager.isValid(session))
baseRequest.setSession(session);
}
/* ------------------------------------------------------------ */

View File

@ -23,10 +23,9 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.StringTokenizer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.Before;
import org.junit.Test;
/**
@ -49,17 +48,13 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private static int __length = __content.length();
private StringBuffer _response;
private boolean _continue;
/* ------------------------------------------------------------ */
@Test
public void testCloseBetweenRequests() throws Exception
{
int total = 0;
_continue = true;
_response = new StringBuffer();
int maxLength = 32;
int requestCount = iterations(maxLength);
final CountDownLatch latch = new CountDownLatch(requestCount);
configureServer(new HelloWorldHandler());
@ -68,17 +63,36 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
{
OutputStream os = client.getOutputStream();
ResponseReader reader = new ResponseReader(client);
ResponseReader reader = new ResponseReader(client) {
private int _index = 0;
/* ------------------------------------------------------------ */
@Override
protected int doRead() throws IOException, InterruptedException
{
int count = super.doRead();
if (count > 0)
{
int idx;
while ((idx=_response.indexOf("HTTP/1.1 200 OK", _index)) >= 0)
{
latch.countDown();
_index = idx + 15;
}
}
return count;
}
};
Thread runner = new Thread(reader);
runner.start();
for (int pipeline = 1; pipeline < 32; pipeline++)
for (int pipeline = 1; pipeline < maxLength; pipeline++)
{
if (pipeline == 16)
if (pipeline == maxLength / 2)
_connector.close();
total += pipeline;
String request = "";
for (int i = 0; i < pipeline; i++)
{
@ -93,38 +107,32 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
os.write(request.getBytes());
os.flush();
Thread.sleep(50);
Thread.sleep(25);
}
_continue = false;
latch.await(30, TimeUnit.SECONDS);
reader.setDone();
runner.join();
}
finally
{
client.close();
int count = 0;
StringTokenizer lines = new StringTokenizer(_response.toString(),"\r\n");
while(lines.hasMoreTokens())
{
String line = lines.nextToken();
if (line.equals("HTTP/1.1 200 OK"))
{
++count;
}
}
assertEquals(total, count);
assertEquals(requestCount, requestCount - latch.getCount());
}
}
/* ------------------------------------------------------------ */
private int iterations(int cnt)
{
return cnt > 0 ? iterations(--cnt) + cnt : 0;
}
/* ------------------------------------------------------------ */
@Test
public void testCloseBetweenChunks() throws Exception
{
_continue = true;
_response = new StringBuffer();
configureServer(new EchoHandler());
Socket client = newSocket(HOST,_connector.getLocalPort());
@ -136,7 +144,6 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
Thread runner = new Thread(reader);
runner.start();
String content = "abcdefghij";
byte[] bytes = __content.getBytes("utf-8");
os.write((
@ -154,6 +161,7 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
{
os.write(bytes, offset, 64);
offset += 64;
Thread.sleep(25);
}
_connector.close();
@ -162,15 +170,14 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
{
os.write(bytes, offset, len-offset <=64 ? len-offset : 64);
offset += 64;
Thread.sleep(25);
}
os.flush();
Thread.sleep(50);
_continue = false;
reader.setDone();
runner.join();
String in = _response.toString();
String in = reader.getResponse().toString();
assertTrue(in.indexOf(__content.substring(__length-64))>0);
}
finally
@ -183,38 +190,44 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
/* ------------------------------------------------------------ */
public class ResponseReader implements Runnable
{
private BufferedReader _reader;
private int _last = 0;
private boolean _done = false;
protected char[] _buffer;
protected StringBuffer _response;
protected BufferedReader _reader;
/* ------------------------------------------------------------ */
public ResponseReader(Socket client) throws IOException
{
_buffer = new char[256];
_response = new StringBuffer();
_reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
}
/* ------------------------------------------------------------ */
public void setDone()
{
_done = true;
}
public StringBuffer getResponse()
{
return _response;
}
/* ------------------------------------------------------------ */
/**
* @see java.lang.Runnable#run()
*/
public void run()
{
int count = 0;
char[] buffer = new char[256];
try
{
while (_continue)
int count = 0;
while (!_done || _last > 0 || count > 0)
{
if (_reader.ready())
{
count = _reader.read(buffer);
_response.append(buffer, 0, count);
}
else
{
count = 0;
Thread.sleep(10);
}
count = doRead();
}
}
catch (IOException ex) { }
@ -228,5 +241,29 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
catch (IOException e) { }
}
}
/* ------------------------------------------------------------ */
protected int doRead() throws IOException, InterruptedException
{
if (_last > 0)
{
_last = 0;
Thread.sleep(25);
}
int count = 0;
if (_reader.ready())
{
count = _reader.read(_buffer);
if (count > 0)
{
_last = count;
_response.append(_buffer, 0, count);
}
}
return count;
}
}
}

View File

@ -40,6 +40,7 @@ import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.session.AbstractSession;
import org.eclipse.jetty.server.session.AbstractSessionManager;
import org.eclipse.jetty.server.session.HashSessionIdManager;
import org.eclipse.jetty.server.session.HashSessionManager;
@ -330,7 +331,7 @@ public class ResponseTest
request.setRequestedSessionId("12345");
request.setRequestedSessionIdFromCookie(false);
AbstractSessionManager manager=new HashSessionManager();
manager.setIdManager(new HashSessionIdManager());
manager.setSessionIdManager(new HashSessionIdManager());
request.setSessionManager(manager);
request.setSession(new TestSession(manager,"12345"));
@ -378,7 +379,7 @@ public class ResponseTest
request.setRequestedSessionId("12345");
request.setRequestedSessionIdFromCookie(false);
AbstractSessionManager manager=new HashSessionManager();
manager.setIdManager(new HashSessionIdManager());
manager.setSessionIdManager(new HashSessionIdManager());
request.setSessionManager(manager);
request.setSession(new TestSession(manager,"12345"));
manager.setCheckingRemoteSessionIdEncoding(false);
@ -471,11 +472,11 @@ public class ResponseTest
return response;
}
private class TestSession extends AbstractSessionManager.Session
private class TestSession extends AbstractSession
{
public TestSession(AbstractSessionManager abstractSessionManager, String id)
{
abstractSessionManager.super(System.currentTimeMillis(),System.currentTimeMillis(), id);
super(abstractSessionManager, System.currentTimeMillis(),System.currentTimeMillis(), id);
}
public Object getAttribute(String name)

View File

@ -271,7 +271,7 @@ public class ContextHandlerTest
ContextHandler handler = new ContextHandler();
assertTrue("Not a directory " + testDirectory,testDirectory.isDirectory());
handler.setBaseResource(Resource.newResource(testDirectory.toURI().toURL()));
handler.setBaseResource(Resource.newResource(Resource.toURL(testDirectory)));
List<String> paths = new ArrayList<String>(handler.getResourcePaths(root));
assertEquals(2,paths.size());

View File

@ -60,7 +60,7 @@ public class SessionHandlerTest
return cookieName;
}
});
sessionHandler.setRequestedId(baseRequest,httpRequest);
sessionHandler.checkRequestedSessionId(baseRequest,httpRequest);
assertEquals(sessionId,baseRequest.getRequestedSessionId());
assertTrue(baseRequest.isRequestedSessionIdFromCookie());
@ -100,7 +100,7 @@ public class SessionHandlerTest
}
});
sessionHandler.setRequestedId(baseRequest,httpRequest);
sessionHandler.checkRequestedSessionId(baseRequest,httpRequest);
assertEquals(sessionId,baseRequest.getRequestedSessionId());
assertFalse(baseRequest.isRequestedSessionIdFromCookie());
@ -417,7 +417,7 @@ public class SessionHandlerTest
return null;
}
public SessionIdManager getIdManager()
public SessionIdManager getSessionIdManager()
{
return null;
}
@ -496,7 +496,7 @@ public class SessionHandlerTest
{
}
public void setIdManager(SessionIdManager idManager)
public void setSessionIdManager(SessionIdManager idManager)
{
}

View File

@ -127,7 +127,7 @@ public class Classpath {
URL[] urls = new URL[cnt];
for (int i=0; i < cnt; i++) {
try {
String u=((_elements.elementAt(i))).toURL().toString();
String u=_elements.elementAt(i).toURI().toURL().toString();
urls[i] = new URL(encodeFileURL(u));
} catch (MalformedURLException e) {}
}

View File

@ -183,7 +183,7 @@ public class FileResource extends URLResource
String can=_file.getCanonicalPath();
if (abs.length()!=can.length() || !abs.equals(can))
_alias=new File(can).toURI().toURL();
_alias=Resource.toURL(new File(can));
_aliasChecked=true;

View File

@ -160,7 +160,7 @@ public abstract class Resource implements ResourceFactory
resource=resource.substring(2);
File file=new File(resource).getCanonicalFile();
url=file.toURI().toURL();
url=Resource.toURL(file);
URLConnection connection=url.openConnection();
connection.setUseCaches(useCaches);
@ -642,5 +642,15 @@ public abstract class Resource implements ResourceFactory
throw new IllegalArgumentException(destination+" exists");
writeTo(new FileOutputStream(destination),0,-1);
}
/* ------------------------------------------------------------ */
/** Generate a properly encoded URL from a {@link File} instance.
* @param file Target file.
* @return URL of the target file.
* @throws MalformedURLException
*/
public static URL toURL(File file) throws MalformedURLException
{
return file.toURI().toURL();
}
}

View File

@ -31,6 +31,7 @@ import javax.xml.parsers.SAXParserFactory;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
@ -212,7 +213,7 @@ public class XmlParser
{
if (Log.isDebugEnabled())
Log.debug("parse: " + file);
return parse(new InputSource(file.toURL().toString()));
return parse(new InputSource(Resource.toURL(file).toString()));
}
/* ------------------------------------------------------------ */

View File

@ -41,7 +41,7 @@ public class HashTestServer extends AbstractTestServer
return new HashSessionIdManager();
}
public AbstractSessionManager newSessionManager()
public SessionManager newSessionManager()
{
HashSessionManager manager = new HashSessionManager();
manager.setScavengePeriod((int)TimeUnit.SECONDS.toMillis(_scavengePeriod));

View File

@ -76,10 +76,10 @@ public class JdbcTestServer extends AbstractTestServer
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionManager()
*/
@Override
public AbstractSessionManager newSessionManager()
public SessionManager newSessionManager()
{
JDBCSessionManager manager = new JDBCSessionManager();
manager.setIdManager((JDBCSessionIdManager)_sessionIdManager);
manager.setSessionIdManager((JDBCSessionIdManager)_sessionIdManager);
manager.setSaveInterval(SAVE_INTERVAL); //ensure we save any changes to the session at least once per second
return manager;
}

View File

@ -0,0 +1,33 @@
//========================================================================
//Copyright 2010 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 org.eclipse.jetty.util.log.Log;
import org.junit.Test;
/**
* LastAccessTimeTest
*/
public class SessionValueSavingTest extends AbstractSessionValueSavingTest
{
public AbstractTestServer createServer(int port, int max, int scavenge)
{
return new JdbcTestServer(port,max,scavenge);
}
@Override
public void testSessionValueSaving() throws Exception
{
super.testSessionValueSaving();
}
}

View File

@ -83,7 +83,7 @@ public abstract class AbstractImmortalSessionTest
exchange.waitForDone();
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
response = exchange.getResponseContent();
assertEquals(response.trim(),String.valueOf(value));
assertEquals(String.valueOf(value),response.trim());
}
finally
{
@ -113,7 +113,8 @@ public abstract class AbstractImmortalSessionTest
else if ("get".equals(action))
{
HttpSession session = request.getSession(false);
result = (String)session.getAttribute("value");
if (session!=null)
result = (String)session.getAttribute("value");
}
PrintWriter writer = response.getWriter();
writer.println(result);

View File

@ -109,7 +109,6 @@ public abstract class AbstractLastAccessTimeTest
exchange1.waitForDone();
assertEquals(HttpServletResponse.SC_OK, exchange1.getResponseStatus());
// TODO shouldn't the session be expired????
}
finally
{
@ -141,7 +140,8 @@ public abstract class AbstractLastAccessTimeTest
else
{
HttpSession session = request.getSession(false);
session.setAttribute("test", "test");
if (session!=null)
session.setAttribute("test", "test");
}
}
}

View File

@ -86,6 +86,15 @@ public abstract class AbstractOrphanedSessionTest
System.err.println("FINISHED waiting for session to expire");
// Perform one request to server2 to be sure that the session has been expired
//
// force invalidate to test
// ContentExchange exchange3 = new ContentExchange(true);
// exchange3.setMethod(HttpMethods.GET);
// exchange3.setURL("http://localhost:" + port2 + contextPath + servletMapping + "?action=remove");
// exchange3.getRequestFields().add("Cookie", sessionCookie);
// client.send(exchange3);
// exchange3.waitForDone();
System.err.println("CHECKING NODE2");
ContentExchange exchange2 = new ContentExchange(true);
@ -123,6 +132,12 @@ public abstract class AbstractOrphanedSessionTest
HttpSession session = request.getSession(true);
session.setAttribute("A", "A");
}
else if ("remove".equals(action))
{
HttpSession session = request.getSession(false);
session.invalidate();
//assertTrue(session == null);
}
else if ("check".equals(action))
{
HttpSession session = request.getSession(false);

View File

@ -83,11 +83,12 @@ public abstract class AbstractReentrantRequestSessionTest
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
HttpSession session = request.getSession(false);
if (session == null) session = request.getSession(true);
String action = request.getParameter("action");
if ("reenter".equals(action))
{
if (session == null)
session = request.getSession(true);
int port = Integer.parseInt(request.getParameter("port"));
String path = request.getParameter("path");
@ -103,10 +104,11 @@ public abstract class AbstractReentrantRequestSessionTest
{
ContentExchange exchange = new ContentExchange(true);
exchange.setMethod(HttpMethods.GET);
exchange.setURL("http://localhost:" + port + path + "?action=none");
exchange.setURL("http://localhost:" + port + path + ";jsessionid="+session.getId()+"?action=none");
client.send(exchange);
exchange.waitForDone();
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
assertEquals("true",session.getAttribute("reentrant"));
}
finally
{
@ -120,7 +122,8 @@ public abstract class AbstractReentrantRequestSessionTest
}
else
{
// Reentrancy was successful, just return
assertTrue(session!=null);
session.setAttribute("reentrant","true");
}
}
}

View File

@ -3,7 +3,6 @@ package org.eclipse.jetty.server.session;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

View File

@ -0,0 +1,166 @@
// ========================================================================
// Copyright 2004-2010 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.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.http.HttpMethods;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* AbstractLastAccessTimeTest
*/
public abstract class AbstractSessionValueSavingTest
{
public abstract AbstractTestServer createServer(int port, int max, int scavenge);
@Test
public void testSessionValueSaving() throws Exception
{
String contextPath = "";
String servletMapping = "/server";
int maxInactivePeriod = 10000;
int scavengePeriod = 20000;
AbstractTestServer server1 = createServer(0, maxInactivePeriod, scavengePeriod);
server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
server1.start();
int port1=server1.getPort();
try
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
client.start();
try
{
long sessionTestValue = 0;
// Perform one request to server1 to create a session
ContentExchange exchange1 = new ContentExchange(true);
exchange1.setMethod(HttpMethods.GET);
exchange1.setURL("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
client.send(exchange1);
exchange1.waitForDone();
assertEquals(HttpServletResponse.SC_OK, exchange1.getResponseStatus());
System.out.println("Checking: " + sessionTestValue + " vs " + exchange1.getResponseContent());
assertTrue(sessionTestValue < Long.parseLong(exchange1.getResponseContent()));
sessionTestValue = Long.parseLong(exchange1.getResponseContent());
String sessionCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
assertTrue( sessionCookie != null );
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
// Perform some request to server2 using the session cookie from the previous request
// This should migrate the session from server1 to server2, and leave server1's
// session in a very stale state, while server2 has a very fresh session.
// We want to test that optimizations done to the saving of the shared lastAccessTime
// do not break the correct working
int requestInterval = 500;
for (int i = 0; i < 10; ++i)
{
ContentExchange exchange2 = new ContentExchange(true);
exchange2.setMethod(HttpMethods.GET);
exchange2.setURL("http://localhost:" + port1 + contextPath + servletMapping);
exchange2.getRequestFields().add("Cookie", sessionCookie);
client.send(exchange2);
exchange2.waitForDone();
assertEquals(HttpServletResponse.SC_OK , exchange2.getResponseStatus());
System.out.println("Checking: " + sessionTestValue + " vs " + exchange2.getResponseContent());
assertTrue(sessionTestValue < Long.parseLong(exchange2.getResponseContent()));
sessionTestValue = Long.parseLong(exchange2.getResponseContent());
String setCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
if (setCookie!=null)
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
Thread.sleep(requestInterval);
}
}
finally
{
client.stop();
}
}
finally
{
server1.stop();
}
}
public static class TestServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
String action = request.getParameter("action");
if ("init".equals(action))
{
HttpSession session = request.getSession(true);
session.setAttribute("test", System.currentTimeMillis());
sendResult(session, httpServletResponse.getWriter());
}
else
{
HttpSession session = request.getSession(false);
System.out.println("not init call " + session);
if (session!=null)
{
long value = System.currentTimeMillis();
System.out.println("Setting test to : " + value);
session.setAttribute("test", value);
}
sendResult(session, httpServletResponse.getWriter());
}
}
private void sendResult(HttpSession session, PrintWriter writer)
{
if (session != null)
{
writer.print(session.getAttribute("test"));
}
else
{
writer.print(0);
}
}
}
}

View File

@ -50,7 +50,7 @@ public abstract class AbstractTestServer
public abstract SessionIdManager newSessionIdManager();
public abstract AbstractSessionManager newSessionManager();
public abstract SessionManager newSessionManager();
public abstract SessionHandler newSessionHandler(SessionManager sessionManager);
@ -70,8 +70,8 @@ public abstract class AbstractTestServer
{
ServletContextHandler context = new ServletContextHandler(_contexts, contextPath);
AbstractSessionManager sessionManager = newSessionManager();
sessionManager.setIdManager(_sessionIdManager);
SessionManager sessionManager = newSessionManager();
sessionManager.setSessionIdManager(_sessionIdManager);
sessionManager.setMaxInactiveInterval(_maxInactivePeriod);
SessionHandler sessionHandler = newSessionHandler(sessionManager);
@ -86,12 +86,17 @@ public abstract class AbstractTestServer
_server.stop();
}
public void join() throws Exception
{
_server.join();
}
public WebAppContext addWebAppContext(String warPath, String contextPath)
{
WebAppContext context = new WebAppContext(_contexts, warPath, contextPath);
AbstractSessionManager sessionManager = newSessionManager();
sessionManager.setIdManager(_sessionIdManager);
SessionManager sessionManager = newSessionManager();
sessionManager.setSessionIdManager(_sessionIdManager);
sessionManager.setMaxInactiveInterval(_maxInactivePeriod);
SessionHandler sessionHandler = newSessionHandler(sessionManager);