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 jetty-7.4.4.v20110707 July 7th 2011
+ 308851 Converted all jetty-client module tests to JUnit 4 + 308851 Converted all jetty-client module tests to JUnit 4
+ 345268 JDBCSessionManager does not work with maxInactiveInterval = -1 + 345268 JDBCSessionManager does not work with maxInactiveInterval = -1

View File

@ -219,7 +219,7 @@ public class ContextDeployer extends AbstractLifeCycle
@Deprecated @Deprecated
public void setConfigurationDir(File file) throws Exception 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(); WebAppContext context = new WebAppContext();
File war = new File(webappsDir,app.getOriginId().substring(5)); 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(); 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.PathAssert;
import org.eclipse.jetty.toolchain.test.TestingDir; import org.eclipse.jetty.toolchain.test.TestingDir;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration; import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.Assert; import org.junit.Assert;
@ -132,7 +133,7 @@ public class XmlConfiguredJetty
public void addConfiguration(File xmlConfigFile) throws MalformedURLException public void addConfiguration(File xmlConfigFile) throws MalformedURLException
{ {
_xmlConfigurations.add(xmlConfigFile.toURI().toURL()); _xmlConfigurations.add(Resource.toURL(xmlConfigFile));
} }
public void addConfiguration(String testConfigName) throws MalformedURLException 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) * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
*/ */
public HttpSession getSession(boolean create) 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"); throw new IllegalStateException("No SessionManager");
if (_session != null && _sessionManager!=null && _sessionManager.isValid(_session)) _session=_sessionManager.newHttpSession(this);
return _session; HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
if (cookie!=null)
_session=null; _connection.getResponse().addCookie(cookie);
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);
}
return _session; return _session;
} }
@ -1292,7 +1286,7 @@ public class Request implements HttpServletRequest
return false; return false;
HttpSession session=getSession(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. * @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. * @return the cross context session id manager.
* @deprecated use {@link #getIdManager()} * @deprecated use {@link #getSessionIdManager()}
*/ */
@Deprecated @Deprecated
public SessionIdManager getMetaManager(); public SessionIdManager getMetaManager();
@ -204,9 +204,9 @@ public interface SessionManager extends LifeCycle
* Sets the cross context session id manager * Sets the cross context session id manager
* *
* @param idManager 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 static java.lang.Math.round;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.EventListener; import java.util.EventListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext; import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener; 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.SessionIdManager;
import org.eclipse.jetty.server.SessionManager; import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.server.handler.ContextHandler; 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.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.CounterStatistic;
import org.eclipse.jetty.util.statistic.SampleStatistic; 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 * a specialised version of the Session inner class that provides an attribute
* Map. * Map.
* <p> * <p>
*
*
*/ */
@SuppressWarnings("deprecation")
public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager 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; 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; private boolean _usingCookies=true;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -79,8 +85,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
protected boolean _httpOnly=false; protected boolean _httpOnly=false;
protected SessionIdManager _sessionIdManager; protected SessionIdManager _sessionIdManager;
protected boolean _secureCookies=false; protected boolean _secureCookies=false;
protected Object _sessionAttributeListeners; protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
protected Object _sessionListeners; protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
protected ClassLoader _loader; protected ClassLoader _loader;
protected ContextHandler.Context _context; 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) public HttpCookie access(HttpSession session,boolean secure)
{ {
long now=System.currentTimeMillis(); long now=System.currentTimeMillis();
Session s = ((SessionIf)session).getSession(); AbstractSession s = ((SessionIf)session).getSession();
s.access(now);
// Do we need to refresh the cookie? if (s.access(now))
if (isUsingCookies() &&
(s.isIdChanged() ||
(getMaxCookieAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
)
)
{ {
HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure); // Do we need to refresh the cookie?
s.cookieSet(); if (isUsingCookies() &&
s.setIdChanged(false); (s.isIdChanged() ||
return cookie; (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; return null;
} }
@ -130,22 +149,22 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
public void addEventListener(EventListener listener) public void addEventListener(EventListener listener)
{ {
if (listener instanceof HttpSessionAttributeListener) if (listener instanceof HttpSessionAttributeListener)
_sessionAttributeListeners=LazyList.add(_sessionAttributeListeners,listener); _sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
if (listener instanceof HttpSessionListener) if (listener instanceof HttpSessionListener)
_sessionListeners=LazyList.add(_sessionListeners,listener); _sessionListeners.add((HttpSessionListener)listener);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void clearEventListeners() public void clearEventListeners()
{ {
_sessionAttributeListeners=null; _sessionAttributeListeners.clear();
_sessionListeners=null; _sessionListeners.clear();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void complete(HttpSession session) public void complete(HttpSession session)
{ {
Session s = ((SessionIf)session).getSession(); AbstractSession s = ((SessionIf)session).getSession();
s.complete(); s.complete();
} }
@ -230,20 +249,29 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public HttpSession getHttpSession(String nodeId) 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)) if (session!=null && !session.getNodeId().equals(nodeId))
session.setIdChanged(true); session.setIdChanged(true);
return session; return session;
} }
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return Returns the metaManager used for cross context session management * @return Returns the metaManager used for cross context session management
* @deprecated Use {@link #getSessionIdManager()}
*/ */
public SessionIdManager getIdManager() public SessionIdManager getIdManager()
{
return getSessionIdManager();
}
/* ------------------------------------------------------------ */
/**
* @return Returns the SessionIdManager used for cross context session management
*/
public SessionIdManager getSessionIdManager()
{ {
return _sessionIdManager; return _sessionIdManager;
} }
@ -293,12 +321,12 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @deprecated use {@link #getIdManager()} * @deprecated use {@link #getSessionIdManager()}
*/ */
@Deprecated @Deprecated
public SessionIdManager getMetaManager() 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. * @deprecated Need to review if it is needed.
*/ */
public abstract Map getSessionMap(); @SuppressWarnings("rawtypes")
public Map getSessionMap()
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public String getSessionPath() public String getSessionPath()
@ -411,21 +443,21 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public boolean isValid(HttpSession session) public boolean isValid(HttpSession session)
{ {
Session s = ((SessionIf)session).getSession(); AbstractSession s = ((SessionIf)session).getSession();
return s.isValid(); return s.isValid();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public String getClusterId(HttpSession session) public String getClusterId(HttpSession session)
{ {
Session s = ((SessionIf)session).getSession(); AbstractSession s = ((SessionIf)session).getSession();
return s.getClusterId(); return s.getClusterId();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public String getNodeId(HttpSession session) public String getNodeId(HttpSession session)
{ {
Session s = ((SessionIf)session).getSession(); AbstractSession s = ((SessionIf)session).getSession();
return s.getNodeId(); return s.getNodeId();
} }
@ -435,7 +467,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
*/ */
public HttpSession newHttpSession(HttpServletRequest request) public HttpSession newHttpSession(HttpServletRequest request)
{ {
Session session=newSession(request); AbstractSession session=newSession(request);
session.setMaxInactiveInterval(_dftMaxIdleSecs); session.setMaxInactiveInterval(_dftMaxIdleSecs);
addSession(session,true); addSession(session,true);
return session; return session;
@ -445,9 +477,9 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
public void removeEventListener(EventListener listener) public void removeEventListener(EventListener listener)
{ {
if (listener instanceof HttpSessionAttributeListener) if (listener instanceof HttpSessionAttributeListener)
_sessionAttributeListeners=LazyList.remove(_sessionAttributeListeners,listener); _sessionAttributeListeners.remove(listener);
if (listener instanceof HttpSessionListener) 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; _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. * @param metaManager The metaManager used for cross context session management.
*/ */
public void setIdManager(SessionIdManager metaManager) public void setSessionIdManager(SessionIdManager metaManager)
{ {
_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 @Deprecated
public void setMetaManager(SessionIdManager metaManager) 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 * Add the session Registers the session with this manager and registers the
* session ID with the sessionIDManager; * session ID with the sessionIDManager;
*/ */
protected void addSession(Session session, boolean created) protected void addSession(AbstractSession session, boolean created)
{ {
synchronized (_sessionIdManager) synchronized (_sessionIdManager)
{ {
@ -612,8 +653,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
if (_sessionListeners!=null) if (_sessionListeners!=null)
{ {
HttpSessionEvent event=new HttpSessionEvent(session); HttpSessionEvent event=new HttpSessionEvent(session);
for (int i=0; i<LazyList.size(_sessionListeners); i++) for (HttpSessionListener listener : _sessionListeners)
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionCreated(event); 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. * @param idInCluster The session ID in the cluster, stripped of any worker name.
* @return A Session or null if none exists. * @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; protected abstract void invalidateSessions() throws Exception;
@ -635,7 +676,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
* @param request * @param request
* @return the new session * @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) public void removeSession(HttpSession session, boolean invalidate)
{ {
Session s = ((SessionIf)session).getSession(); AbstractSession s = ((SessionIf)session).getSession();
removeSession(s,invalidate); removeSession(s,invalidate);
} }
@ -674,7 +715,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and * @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
* {@link SessionIdManager#invalidateAll(String)} should be called. * {@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 // Remove session from context and global maps
boolean removed = removeSession(session.getClusterId()); boolean removed = removeSession(session.getClusterId());
@ -692,8 +733,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
if (invalidate && _sessionListeners!=null) if (invalidate && _sessionListeners!=null)
{ {
HttpSessionEvent event=new HttpSessionEvent(session); HttpSessionEvent event=new HttpSessionEvent(session);
for (int i=LazyList.size(_sessionListeners); i-->0;) for (HttpSessionListener listener : _sessionListeners)
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionDestroyed(event); listener.sessionCreated(event);
} }
} }
} }
@ -754,41 +795,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
{ {
_checkingRemoteSessionIdEncoding=remote; _checkingRemoteSessionIdEncoding=remote;
} }
/* ------------------------------------------------------------ */
/**
* Null returning implementation of HttpSessionContext
*
*
*/
public static class NullSessionContext implements HttpSessionContext
{
/* ------------------------------------------------------------ */
private NullSessionContext()
{
}
/* ------------------------------------------------------------ */
/**
* @deprecated From HttpSessionContext
*/
@Deprecated
public Enumeration getIds()
{
return Collections.enumeration(Collections.EMPTY_LIST);
}
/* ------------------------------------------------------------ */
/**
* @deprecated From HttpSessionContext
*/
@Deprecated
public HttpSession getSession(String id)
{
return null;
}
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -799,496 +806,23 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
*/ */
public interface SessionIf extends HttpSession public interface SessionIf extends HttpSession
{ {
public Session getSession(); public AbstractSession getSession();
} }
/* ------------------------------------------------------------ */ public void doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value)
/**
*
* <p>
* Implements {@link javax.servlet.http.HttpSession} from the <code>javax.servlet</code> package.
* </p>
*
*
*/
public abstract class Session implements SessionIf, Serializable
{ {
protected final String _clusterId; // ID unique within cluster if (!_sessionAttributeListeners.isEmpty())
protected final String _nodeId; // ID unique within node {
protected final Map<String,Object> _attributes=new HashMap<String, Object>(); HttpSessionBindingEvent event=new HttpSessionBindingEvent(session,name,old==null?value:old);
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;
/* ------------------------------------------------------------- */ for (HttpSessionAttributeListener l : _sessionAttributeListeners)
protected Session(HttpServletRequest request)
{
_newSession=true;
_created=System.currentTimeMillis();
_clusterId=_sessionIdManager.newSessionId(request,_created);
_nodeId=_sessionIdManager.getNodeId(_clusterId,request);
_accessed=_created;
_lastAccessed=_created;
_requests=1;
Log.debug("new session & id "+_nodeId+" "+_clusterId);
}
/* ------------------------------------------------------------- */
protected Session(long created, long accessed, String clusterId)
{
_created=created;
_clusterId=clusterId;
_nodeId=_sessionIdManager.getNodeId(_clusterId,null);
_accessed=accessed;
_lastAccessed=accessed;
_requests=1;
Log.debug("new session "+_nodeId+" "+_clusterId);
}
/* ------------------------------------------------------------- */
/**
* @return True is the session is invalid or passivated.
*/
protected boolean isNotAvailable()
{
return _invalid;
}
/* ------------------------------------------------------------- */
public Session getSession()
{
return this;
}
/* ------------------------------------------------------------ */
public Object getAttribute(String name)
{
synchronized (Session.this)
{ {
if (isNotAvailable()) if (old==null)
throw new IllegalStateException(); l.attributeAdded(event);
else if (value==null)
return _attributes.get(name); l.attributeRemoved(event);
} else
} l.attributeReplaced(event);
/* ------------------------------------------------------------ */
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);
}
}
} }
} }
} }

View File

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

View File

@ -14,16 +14,11 @@
package org.eclipse.jetty.server.session; package org.eclipse.jetty.server.session;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
@ -37,8 +32,8 @@ import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.server.handler.ContextHandler; 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.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -53,16 +48,18 @@ import org.eclipse.jetty.util.log.Log;
*/ */
public class HashSessionManager extends AbstractSessionManager public class HashSessionManager extends AbstractSessionManager
{ {
final static Logger __log = SessionHandler.__log;
protected final ConcurrentMap<String,HashedSession> _sessions=new ConcurrentHashMap<String,HashedSession>(); protected final ConcurrentMap<String,HashedSession> _sessions=new ConcurrentHashMap<String,HashedSession>();
private static int __id; private static int __id;
private Timer _timer; private Timer _timer;
private boolean _timerStop=false; private boolean _timerStop=false;
private TimerTask _task; private TimerTask _task;
private int _scavengePeriodMs=30000; int _scavengePeriodMs=30000;
private int _savePeriodMs=0; //don't do period saves by default int _savePeriodMs=0; //don't do period saves by default
private int _idleSavePeriodMs = 0; // don't idle save sessions by default. int _idleSavePeriodMs = 0; // don't idle save sessions by default.
private TimerTask _saveTask; private TimerTask _saveTask;
private File _storeDir; File _storeDir;
private boolean _lazyLoad=false; private boolean _lazyLoad=false;
private volatile boolean _sessionsLoaded=false; private volatile boolean _sessionsLoaded=false;
@ -142,24 +139,16 @@ public class HashSessionManager extends AbstractSessionManager
return _scavengePeriodMs/1000; return _scavengePeriodMs/1000;
} }
/* ------------------------------------------------------------ */
@Override
public Map getSessionMap()
{
return Collections.unmodifiableMap(_sessions);
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public int getSessions() public int getSessions()
{ {
int sessions=super.getSessions(); int sessions=super.getSessions();
if (Log.isDebugEnabled()) if (__log.isDebugEnabled())
{ {
if (_sessions.size()!=sessions) if (_sessions.size()!=sessions)
Log.warn("sessions: "+_sessions.size()+"!="+sessions); __log.warn("sessions: "+_sessions.size()+"!="+sessions);
} }
return sessions; return sessions;
} }
@ -229,7 +218,7 @@ public class HashSessionManager extends AbstractSessionManager
} }
catch (Exception e) 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();) for (Iterator<HashedSession> i=_sessions.values().iterator(); i.hasNext();)
{ {
HashedSession session=i.next(); HashedSession session=i.next();
long idleTime=session._maxIdleMs; long idleTime=session.getMaxInactiveInterval()*1000;
if (idleTime>0&&session._accessed+idleTime<now) if (idleTime>0&&session.getAccessed()+idleTime<now)
{ {
// Found a stale session, add it to the list // Found a stale session, add it to the list
session.timeout(); session.timeout();
} }
else if (_idleSavePeriodMs>0&&session._accessed+_idleSavePeriodMs<now) else if (_idleSavePeriodMs>0&&session.getAccessed()+_idleSavePeriodMs<now)
{ {
session.idle(); session.idle();
} }
@ -327,7 +316,7 @@ public class HashSessionManager extends AbstractSessionManager
if (t instanceof ThreadDeath) if (t instanceof ThreadDeath)
throw ((ThreadDeath)t); throw ((ThreadDeath)t);
else else
Log.warn("Problem scavenging sessions", t); __log.warn("Problem scavenging sessions", t);
} }
finally finally
{ {
@ -337,7 +326,7 @@ public class HashSessionManager extends AbstractSessionManager
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
protected void addSession(AbstractSessionManager.Session session) protected void addSession(AbstractSession session)
{ {
if (isRunning()) if (isRunning())
_sessions.put(session.getClusterId(),(HashedSession)session); _sessions.put(session.getClusterId(),(HashedSession)session);
@ -345,7 +334,7 @@ public class HashSessionManager extends AbstractSessionManager
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public AbstractSessionManager.Session getSession(String idInCluster) public AbstractSession getSession(String idInCluster)
{ {
if ( _lazyLoad && !_sessionsLoaded) if ( _lazyLoad && !_sessionsLoaded)
{ {
@ -355,7 +344,7 @@ public class HashSessionManager extends AbstractSessionManager
} }
catch(Exception e) catch(Exception e)
{ {
Log.warn(e); __log.warn(e);
} }
} }
@ -408,15 +397,15 @@ public class HashSessionManager extends AbstractSessionManager
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @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()) 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; return;
} }
@ -492,7 +481,7 @@ public class HashSessionManager extends AbstractSessionManager
} }
catch (Exception e) catch (Exception e)
{ {
Log.warn("Problem restoring session "+idInCuster, e); __log.warn("Problem restoring session "+idInCuster, e);
} }
return null; return null;
} }
@ -507,7 +496,7 @@ public class HashSessionManager extends AbstractSessionManager
if (!_storeDir.canWrite()) 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; return;
} }
@ -525,23 +514,13 @@ public class HashSessionManager extends AbstractSessionManager
DataInputStream in = new DataInputStream(is); DataInputStream in = new DataInputStream(is);
String clusterId = in.readUTF(); String clusterId = in.readUTF();
String nodeId = in.readUTF(); String nodeId = in.readUTF();
boolean idChanged = in.readBoolean();
long created = in.readLong(); long created = in.readLong();
long cookieSet = in.readLong();
long accessed = 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(); int requests = in.readInt();
if (session == null) if (session == null)
session = (HashedSession)newSession(created, System.currentTimeMillis(), clusterId); session = (HashedSession)newSession(created, accessed, clusterId);
session.setRequests(requests);
session._cookieSet = cookieSet;
session._lastAccessed = lastAccessed;
int size = in.readInt(); int size = in.readInt();
if (size>0) 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 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.SessionManager;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log; 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 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 Server _server;
protected String _driverClassName; protected String _driverClassName;
protected String _connectionUrl; protected String _connectionUrl;
@ -104,7 +107,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
throws SQLException throws SQLException
{ {
_dbName = dbMeta.getDatabaseProductName().toLowerCase(); _dbName = dbMeta.getDatabaseProductName().toLowerCase();
Log.debug ("Using database "+_dbName); __log.debug ("Using database "+_dbName);
_isLower = dbMeta.storesLowerCaseIdentifiers(); _isLower = dbMeta.storesLowerCaseIdentifiers();
_isUpper = dbMeta.storesUpperCaseIdentifiers(); _isUpper = dbMeta.storesUpperCaseIdentifiers();
} }
@ -228,7 +231,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
if ((System.currentTimeMillis()%2) == 0) if ((System.currentTimeMillis()%2) == 0)
_scavengeIntervalMs += tenPercent; _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)) if (_timer!=null && (period!=old_period || _task==null))
{ {
synchronized (this) synchronized (this)
@ -269,7 +272,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
} }
catch (Exception e) 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) synchronized (_sessionIds)
{ {
if (Log.isDebugEnabled()) if (__log.isDebugEnabled())
Log.debug("Removing session id="+id); __log.debug("Removing session id="+id);
try try
{ {
_sessionIds.remove(id); _sessionIds.remove(id);
@ -301,7 +304,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
} }
catch (Exception e) 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) catch (Exception e)
{ {
Log.warn("Problem checking inUse for id="+clusterId, e); __log.warn("Problem checking inUse for id="+clusterId, e);
return false; return false;
} }
} }
@ -407,13 +410,13 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
initializeDatabase(); initializeDatabase();
prepareTables(); prepareTables();
super.doStart(); 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); _timer=new Timer("JDBCSessionScavenger", true);
setScavengeInterval(getScavengeInterval()); setScavengeInterval(getScavengeInterval());
} }
catch (Exception e) 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(); List expiredSessionIds = new ArrayList();
try 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) if (_lastScavengeTime > 0)
{ {
connection = getConnection(); connection = getConnection();
@ -659,7 +662,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
PreparedStatement statement = connection.prepareStatement(_selectExpiredSessions); PreparedStatement statement = connection.prepareStatement(_selectExpiredSessions);
long lowerBound = (_lastScavengeTime - _scavengeIntervalMs); long lowerBound = (_lastScavengeTime - _scavengeIntervalMs);
long upperBound = _lastScavengeTime; 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(1, lowerBound);
statement.setLong(2, upperBound); statement.setLong(2, upperBound);
@ -668,7 +671,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
{ {
String sessionId = result.getString("sessionId"); String sessionId = result.getString("sessionId");
expiredSessionIds.add(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 //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); upperBound = _lastScavengeTime - (2 * _scavengeIntervalMs);
if (upperBound > 0) 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 = connection.prepareStatement(_deleteOldExpiredSessions);
statement.setLong(1, upperBound); statement.setLong(1, upperBound);
statement.executeUpdate(); statement.executeUpdate();
@ -700,12 +703,12 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
} }
catch (Exception e) catch (Exception e)
{ {
Log.warn("Problem selecting expired sessions", e); __log.warn("Problem selecting expired sessions", e);
} }
finally finally
{ {
_lastScavengeTime=System.currentTimeMillis(); _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) if (connection != null)
{ {
try try
@ -714,7 +717,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
} }
catch (SQLException e) catch (SQLException e)
{ {
Log.warn(e); __log.warn(e);
} }
} }
} }

View File

@ -105,7 +105,7 @@ public class JDBCSessionManager extends AbstractSessionManager
_created=System.currentTimeMillis(); _created=System.currentTimeMillis();
_accessed = _created; _accessed = _created;
_attributes = new HashMap<String,Object>(); _attributes = new HashMap<String,Object>();
_lastNode = getIdManager().getWorkerName(); _lastNode = getSessionIdManager().getWorkerName();
} }
public SessionData (String sessionId,Map<String,Object> attributes) public SessionData (String sessionId,Map<String,Object> attributes)
@ -114,7 +114,7 @@ public class JDBCSessionManager extends AbstractSessionManager
_created=System.currentTimeMillis(); _created=System.currentTimeMillis();
_accessed = _created; _accessed = _created;
_attributes = attributes; _attributes = attributes;
_lastNode = getIdManager().getWorkerName(); _lastNode = getSessionIdManager().getWorkerName();
} }
public synchronized String getId () public synchronized String getId ()
@ -260,7 +260,7 @@ public class JDBCSessionManager extends AbstractSessionManager
* *
* Session instance in memory of this node. * 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 static final long serialVersionUID = 5208464051134226143L;
private final SessionData _data; private final SessionData _data;
@ -273,13 +273,14 @@ public class JDBCSessionManager extends AbstractSessionManager
*/ */
protected Session (HttpServletRequest request) protected Session (HttpServletRequest request)
{ {
super(request); super(JDBCSessionManager.this,request);
_data = new SessionData(_clusterId,_attributes); _data = new SessionData(getClusterId(),_jdbcAttributes);
if (_dftMaxIdleSecs>0) if (_dftMaxIdleSecs>0)
_data.setMaxIdleMs(_dftMaxIdleSecs*1000); _data.setMaxIdleMs(_dftMaxIdleSecs*1000);
_data.setCanonicalContext(canonicalize(_context.getContextPath())); _data.setCanonicalContext(canonicalize(_context.getContextPath()));
_data.setVirtualHost(getVirtualHost(_context)); _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) protected Session (long accessed, SessionData data)
{ {
super(data.getCreated(), accessed, data.getId()); super(JDBCSessionManager.this,data.getCreated(), accessed, data.getId());
_data=data; _data=data;
if (_dftMaxIdleSecs>0) if (_dftMaxIdleSecs>0)
_data.setMaxIdleMs(_dftMaxIdleSecs*1000); _data.setMaxIdleMs(_dftMaxIdleSecs*1000);
_attributes.putAll(_data.getAttributeMap()); _jdbcAttributes.putAll(_data.getAttributeMap());
_data.setAttributeMap(_attributes); _data.setAttributeMap(_jdbcAttributes);
} }
@Override @Override
@ -320,20 +321,26 @@ public class JDBCSessionManager extends AbstractSessionManager
* Entry to session. * Entry to session.
* Called by SessionHandler on inbound request and the session already exists in this node's memory. * 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 @Override
protected void access(long time) protected boolean access(long time)
{ {
super.access(time); if (super.access(time))
_data.setLastAccessed(_data.getAccessed()); {
_data.setAccessed(time); _data.setLastAccessed(_data.getAccessed());
_data.setExpiryTime(_maxIdleMs < 0 ? 0 : (time + _maxIdleMs)); _data.setAccessed(time);
int maxInterval=getMaxInactiveInterval();
_data.setExpiryTime(maxInterval <= 0 ? 0 : (time + maxInterval*1000));
return true;
}
return false;
} }
/** /**
* Exit from session * Exit from session
* @see org.eclipse.jetty.server.session.AbstractSessionManager.Session#complete() * @see org.eclipse.jetty.server.session.AbstractSession#complete()
*/ */
@Override @Override
protected void complete() protected void complete()
@ -504,7 +511,7 @@ public class JDBCSessionManager extends AbstractSessionManager
" lastSaved="+(session==null?0:session._data._lastSaved)+ " lastSaved="+(session==null?0:session._data._lastSaved)+
" interval="+(_saveIntervalSec * 1000)+ " interval="+(_saveIntervalSec * 1000)+
" lastNode="+session._data.getLastNode()+ " lastNode="+session._data.getLastNode()+
" thisNode="+getIdManager().getWorkerName()+ " thisNode="+getSessionIdManager().getWorkerName()+
" difference="+(now - session._data._lastSaved)); " difference="+(now - session._data._lastSaved));
} }
@ -526,13 +533,13 @@ public class JDBCSessionManager extends AbstractSessionManager
if (data != null) 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 the session has no expiry, or it is not already expired
if (data._expiryTime <= 0 || data._expiryTime > now) if (data._expiryTime <= 0 || data._expiryTime > now)
{ {
Log.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getIdManager().getWorkerName()); Log.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
data.setLastNode(getIdManager().getWorkerName()); data.setLastNode(getSessionIdManager().getWorkerName());
//session last used on a different node, or we don't have it in memory //session last used on a different node, or we don't have it in memory
session = new Session(now,data); session = new Session(now,data);
_sessions.put(idInCluster, session); _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. * 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. * 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 @Override
protected void addSession(AbstractSessionManager.Session session) protected void addSession(AbstractSession session)
{ {
if (session==null) if (session==null)
return; return;
@ -720,7 +716,7 @@ public class JDBCSessionManager extends AbstractSessionManager
* @see org.eclipse.jetty.server.session.AbstractSessionManager#newSession(javax.servlet.http.HttpServletRequest) * @see org.eclipse.jetty.server.session.AbstractSessionManager#newSession(javax.servlet.http.HttpServletRequest)
*/ */
@Override @Override
protected AbstractSessionManager.Session newSession(HttpServletRequest request) protected AbstractSession newSession(HttpServletRequest request)
{ {
return new Session(request); return new Session(request);
} }
@ -732,7 +728,7 @@ public class JDBCSessionManager extends AbstractSessionManager
* {@link SessionIdManager#invalidateAll(String)} should be called. * {@link SessionIdManager#invalidateAll(String)} should be called.
*/ */
@Override @Override
public void removeSession(AbstractSessionManager.Session session, boolean invalidate) public void removeSession(AbstractSession session, boolean invalidate)
{ {
// Remove session from context and global maps // Remove session from context and global maps
boolean removed = false; boolean removed = false;
@ -755,11 +751,11 @@ public class JDBCSessionManager extends AbstractSessionManager
if (invalidate) if (invalidate)
_sessionIdManager.invalidateAll(session.getClusterId()); _sessionIdManager.invalidateAll(session.getClusterId());
if (invalidate && _sessionListeners!=null) if (invalidate && !_sessionListeners.isEmpty())
{ {
HttpSessionEvent event=new HttpSessionEvent(session); HttpSessionEvent event=new HttpSessionEvent(session);
for (int i=LazyList.size(_sessionListeners); i-->0;) for (HttpSessionListener l : _sessionListeners)
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionDestroyed(event); l.sessionDestroyed(event);
} }
if (!invalidate) if (!invalidate)
{ {
@ -883,7 +879,7 @@ public class JDBCSessionManager extends AbstractSessionManager
data.setCanonicalContext(result.getString("contextPath")); data.setCanonicalContext(result.getString("contextPath"));
data.setVirtualHost(result.getString("virtualHost")); 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); ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream (is);
Object o = ois.readObject(); Object o = ois.readObject();
data.setAttributeMap((Map<String,Object>)o); data.setAttributeMap((Map<String,Object>)o);
@ -946,7 +942,7 @@ public class JDBCSessionManager extends AbstractSessionManager
statement.setString(2, data.getId()); //session id statement.setString(2, data.getId()); //session id
statement.setString(3, data.getCanonicalContext()); //context path statement.setString(3, data.getCanonicalContext()); //context path
statement.setString(4, data.getVirtualHost()); //first vhost 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(6, data.getAccessed());//accessTime
statement.setLong(7, data.getLastAccessed()); //lastAccessTime statement.setLong(7, data.getLastAccessed()); //lastAccessTime
statement.setLong(8, data.getCreated()); //time created statement.setLong(8, data.getCreated()); //time created
@ -997,7 +993,7 @@ public class JDBCSessionManager extends AbstractSessionManager
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
connection.setAutoCommit(true); connection.setAutoCommit(true);
statement = connection.prepareStatement(__updateSession); 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(2, data.getAccessed());//accessTime
statement.setLong(3, data.getLastAccessed()); //lastAccessTime statement.setLong(3, data.getLastAccessed()); //lastAccessTime
statement.setLong(4, now); //last saved time statement.setLong(4, now); //last saved time
@ -1034,7 +1030,7 @@ public class JDBCSessionManager extends AbstractSessionManager
protected void updateSessionNode (SessionData data) protected void updateSessionNode (SessionData data)
throws Exception throws Exception
{ {
String nodeId = getIdManager().getWorkerName(); String nodeId = getSessionIdManager().getWorkerName();
Connection connection = getConnection(); Connection connection = getConnection();
PreparedStatement statement = null; PreparedStatement statement = null;
try try
@ -1071,7 +1067,7 @@ public class JDBCSessionManager extends AbstractSessionManager
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
connection.setAutoCommit(true); connection.setAutoCommit(true);
statement = connection.prepareStatement(__updateSessionAccessTime); statement = connection.prepareStatement(__updateSessionAccessTime);
statement.setString(1, getIdManager().getWorkerName()); statement.setString(1, getSessionIdManager().getWorkerName());
statement.setLong(2, data.getAccessed()); statement.setLong(2, data.getAccessed());
statement.setLong(3, data.getLastAccessed()); statement.setLong(3, data.getLastAccessed());
statement.setLong(4, now); statement.setLong(4, now);
@ -1131,7 +1127,7 @@ public class JDBCSessionManager extends AbstractSessionManager
private Connection getConnection () private Connection getConnection ()
throws SQLException 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.SessionManager;
import org.eclipse.jetty.server.handler.ScopedHandler; import org.eclipse.jetty.server.handler.ScopedHandler;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** SessionHandler. /** SessionHandler.
*/ */
public class SessionHandler extends ScopedHandler public class SessionHandler extends ScopedHandler
{ {
final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session");
/* -------------------------------------------------------------- */ /* -------------------------------------------------------------- */
private SessionManager _sessionManager; private SessionManager _sessionManager;
@ -133,11 +136,9 @@ public class SessionHandler extends ScopedHandler
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException throws IOException, ServletException
{ {
setRequestedId(baseRequest,request);
SessionManager old_session_manager=null; SessionManager old_session_manager=null;
HttpSession old_session=null; HttpSession old_session=null;
HttpSession access=null;
try try
{ {
old_session_manager = baseRequest.getSessionManager(); old_session_manager = baseRequest.getSessionManager();
@ -148,6 +149,7 @@ public class SessionHandler extends ScopedHandler
// new session context // new session context
baseRequest.setSessionManager(_sessionManager); baseRequest.setSessionManager(_sessionManager);
baseRequest.setSession(null); baseRequest.setSession(null);
checkRequestedSessionId(baseRequest,request);
} }
// access any existing session // access any existing session
@ -159,6 +161,7 @@ public class SessionHandler extends ScopedHandler
{ {
if(session!=old_session) if(session!=old_session)
{ {
access=session;
HttpCookie cookie = _sessionManager.access(session,request.isSecure()); HttpCookie cookie = _sessionManager.access(session,request.isSecure());
if (cookie!=null ) // Handle changed ID or max-age refresh if (cookie!=null ) // Handle changed ID or max-age refresh
baseRequest.getResponse().addCookie(cookie); 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("sessionManager="+_sessionManager);
Log.debug("session="+session); __log.debug("session="+session);
} }
// start manual inline of nextScope(target,baseRequest,request,response); // start manual inline of nextScope(target,baseRequest,request,response);
@ -190,20 +193,19 @@ public class SessionHandler extends ScopedHandler
} }
finally finally
{ {
HttpSession session=request.getSession(false); if (access!=null)
_sessionManager.complete(access);
if (old_session_manager != _sessionManager) else
{ {
//leaving context, free up the session HttpSession session = baseRequest.getSession(false);
if (session!=null) if (session!=null && old_session==null)
_sessionManager.complete(session); _sessionManager.complete(session);
}
// Leave last session in place
if (old_session_manager!=null ) if (old_session_manager!=null && old_session_manager != _sessionManager)
{ {
baseRequest.setSessionManager(old_session_manager); baseRequest.setSessionManager(old_session_manager);
baseRequest.setSession(old_session); baseRequest.setSession(old_session);
}
} }
} }
} }
@ -231,13 +233,22 @@ public class SessionHandler extends ScopedHandler
* @param baseRequest * @param baseRequest
* @param request * @param request
*/ */
protected void setRequestedId(Request baseRequest, HttpServletRequest request) protected void checkRequestedSessionId(Request baseRequest, HttpServletRequest request)
{ {
String requested_session_id=request.getRequestedSessionId(); 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; return;
SessionManager sessionManager = getSessionManager();
boolean requested_session_id_from_cookie=false; boolean requested_session_id_from_cookie=false;
HttpSession session=null; HttpSession session=null;
@ -251,22 +262,13 @@ public class SessionHandler extends ScopedHandler
{ {
if (sessionManager.getSessionCookie().equalsIgnoreCase(cookies[i].getName())) 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=cookies[i].getValue();
requested_session_id_from_cookie = true; 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); session=sessionManager.getHttpSession(requested_session_id);
if (session!=null) if (session!=null && sessionManager.isValid(session))
baseRequest.setSession(session); break;
} }
} }
} }
@ -294,14 +296,17 @@ public class SessionHandler extends ScopedHandler
requested_session_id = uri.substring(s,i); requested_session_id = uri.substring(s,i);
requested_session_id_from_cookie = false; requested_session_id_from_cookie = false;
if(Log.isDebugEnabled()) session=sessionManager.getHttpSession(requested_session_id);
Log.debug("Got Session ID "+requested_session_id+" from URL"); if(__log.isDebugEnabled())
__log.debug("Got Session ID "+requested_session_id+" from URL");
} }
} }
} }
baseRequest.setRequestedSessionId(requested_session_id); 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.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; 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; 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."; "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private static int __length = __content.length(); private static int __length = __content.length();
private StringBuffer _response;
private boolean _continue;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Test @Test
public void testCloseBetweenRequests() throws Exception public void testCloseBetweenRequests() throws Exception
{ {
int total = 0; int maxLength = 32;
int requestCount = iterations(maxLength);
_continue = true; final CountDownLatch latch = new CountDownLatch(requestCount);
_response = new StringBuffer();
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
@ -68,17 +63,36 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
{ {
OutputStream os = client.getOutputStream(); 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); Thread runner = new Thread(reader);
runner.start(); 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(); _connector.close();
total += pipeline;
String request = ""; String request = "";
for (int i = 0; i < pipeline; i++) for (int i = 0; i < pipeline; i++)
{ {
@ -93,38 +107,32 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
os.write(request.getBytes()); os.write(request.getBytes());
os.flush(); os.flush();
Thread.sleep(50); Thread.sleep(25);
} }
_continue = false; latch.await(30, TimeUnit.SECONDS);
reader.setDone();
runner.join(); runner.join();
} }
finally finally
{ {
client.close(); client.close();
int count = 0; assertEquals(requestCount, requestCount - latch.getCount());
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);
} }
} }
/* ------------------------------------------------------------ */
private int iterations(int cnt)
{
return cnt > 0 ? iterations(--cnt) + cnt : 0;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Test @Test
public void testCloseBetweenChunks() throws Exception public void testCloseBetweenChunks() throws Exception
{ {
_continue = true;
_response = new StringBuffer();
configureServer(new EchoHandler()); configureServer(new EchoHandler());
Socket client = newSocket(HOST,_connector.getLocalPort()); Socket client = newSocket(HOST,_connector.getLocalPort());
@ -136,7 +144,6 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
Thread runner = new Thread(reader); Thread runner = new Thread(reader);
runner.start(); runner.start();
String content = "abcdefghij";
byte[] bytes = __content.getBytes("utf-8"); byte[] bytes = __content.getBytes("utf-8");
os.write(( os.write((
@ -154,6 +161,7 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
{ {
os.write(bytes, offset, 64); os.write(bytes, offset, 64);
offset += 64; offset += 64;
Thread.sleep(25);
} }
_connector.close(); _connector.close();
@ -162,15 +170,14 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
{ {
os.write(bytes, offset, len-offset <=64 ? len-offset : 64); os.write(bytes, offset, len-offset <=64 ? len-offset : 64);
offset += 64; offset += 64;
Thread.sleep(25);
} }
os.flush(); os.flush();
Thread.sleep(50); reader.setDone();
_continue = false;
runner.join(); runner.join();
String in = _response.toString(); String in = reader.getResponse().toString();
assertTrue(in.indexOf(__content.substring(__length-64))>0); assertTrue(in.indexOf(__content.substring(__length-64))>0);
} }
finally finally
@ -183,38 +190,44 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public class ResponseReader implements Runnable 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 public ResponseReader(Socket client) throws IOException
{ {
_buffer = new char[256];
_response = new StringBuffer();
_reader = new BufferedReader(new InputStreamReader(client.getInputStream())); _reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
} }
/* ------------------------------------------------------------ */
public void setDone()
{
_done = true;
}
public StringBuffer getResponse()
{
return _response;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @see java.lang.Runnable#run() * @see java.lang.Runnable#run()
*/ */
public void run() public void run()
{ {
int count = 0;
char[] buffer = new char[256];
try try
{ {
while (_continue) int count = 0;
while (!_done || _last > 0 || count > 0)
{ {
if (_reader.ready()) count = doRead();
{
count = _reader.read(buffer);
_response.append(buffer, 0, count);
}
else
{
count = 0;
Thread.sleep(10);
}
} }
} }
catch (IOException ex) { } catch (IOException ex) { }
@ -228,5 +241,29 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
catch (IOException e) { } 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.bio.SocketConnector;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler; 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.AbstractSessionManager;
import org.eclipse.jetty.server.session.HashSessionIdManager; import org.eclipse.jetty.server.session.HashSessionIdManager;
import org.eclipse.jetty.server.session.HashSessionManager; import org.eclipse.jetty.server.session.HashSessionManager;
@ -330,7 +331,7 @@ public class ResponseTest
request.setRequestedSessionId("12345"); request.setRequestedSessionId("12345");
request.setRequestedSessionIdFromCookie(false); request.setRequestedSessionIdFromCookie(false);
AbstractSessionManager manager=new HashSessionManager(); AbstractSessionManager manager=new HashSessionManager();
manager.setIdManager(new HashSessionIdManager()); manager.setSessionIdManager(new HashSessionIdManager());
request.setSessionManager(manager); request.setSessionManager(manager);
request.setSession(new TestSession(manager,"12345")); request.setSession(new TestSession(manager,"12345"));
@ -378,7 +379,7 @@ public class ResponseTest
request.setRequestedSessionId("12345"); request.setRequestedSessionId("12345");
request.setRequestedSessionIdFromCookie(false); request.setRequestedSessionIdFromCookie(false);
AbstractSessionManager manager=new HashSessionManager(); AbstractSessionManager manager=new HashSessionManager();
manager.setIdManager(new HashSessionIdManager()); manager.setSessionIdManager(new HashSessionIdManager());
request.setSessionManager(manager); request.setSessionManager(manager);
request.setSession(new TestSession(manager,"12345")); request.setSession(new TestSession(manager,"12345"));
manager.setCheckingRemoteSessionIdEncoding(false); manager.setCheckingRemoteSessionIdEncoding(false);
@ -471,11 +472,11 @@ public class ResponseTest
return response; return response;
} }
private class TestSession extends AbstractSessionManager.Session private class TestSession extends AbstractSession
{ {
public TestSession(AbstractSessionManager abstractSessionManager, String id) 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) public Object getAttribute(String name)

View File

@ -271,7 +271,7 @@ public class ContextHandlerTest
ContextHandler handler = new ContextHandler(); ContextHandler handler = new ContextHandler();
assertTrue("Not a directory " + testDirectory,testDirectory.isDirectory()); 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)); List<String> paths = new ArrayList<String>(handler.getResourcePaths(root));
assertEquals(2,paths.size()); assertEquals(2,paths.size());

View File

@ -60,7 +60,7 @@ public class SessionHandlerTest
return cookieName; return cookieName;
} }
}); });
sessionHandler.setRequestedId(baseRequest,httpRequest); sessionHandler.checkRequestedSessionId(baseRequest,httpRequest);
assertEquals(sessionId,baseRequest.getRequestedSessionId()); assertEquals(sessionId,baseRequest.getRequestedSessionId());
assertTrue(baseRequest.isRequestedSessionIdFromCookie()); assertTrue(baseRequest.isRequestedSessionIdFromCookie());
@ -100,7 +100,7 @@ public class SessionHandlerTest
} }
}); });
sessionHandler.setRequestedId(baseRequest,httpRequest); sessionHandler.checkRequestedSessionId(baseRequest,httpRequest);
assertEquals(sessionId,baseRequest.getRequestedSessionId()); assertEquals(sessionId,baseRequest.getRequestedSessionId());
assertFalse(baseRequest.isRequestedSessionIdFromCookie()); assertFalse(baseRequest.isRequestedSessionIdFromCookie());
@ -417,7 +417,7 @@ public class SessionHandlerTest
return null; return null;
} }
public SessionIdManager getIdManager() public SessionIdManager getSessionIdManager()
{ {
return null; 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]; URL[] urls = new URL[cnt];
for (int i=0; i < cnt; i++) { for (int i=0; i < cnt; i++) {
try { try {
String u=((_elements.elementAt(i))).toURL().toString(); String u=_elements.elementAt(i).toURI().toURL().toString();
urls[i] = new URL(encodeFileURL(u)); urls[i] = new URL(encodeFileURL(u));
} catch (MalformedURLException e) {} } catch (MalformedURLException e) {}
} }

View File

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

View File

@ -160,7 +160,7 @@ public abstract class Resource implements ResourceFactory
resource=resource.substring(2); resource=resource.substring(2);
File file=new File(resource).getCanonicalFile(); File file=new File(resource).getCanonicalFile();
url=file.toURI().toURL(); url=Resource.toURL(file);
URLConnection connection=url.openConnection(); URLConnection connection=url.openConnection();
connection.setUseCaches(useCaches); connection.setUseCaches(useCaches);
@ -642,5 +642,15 @@ public abstract class Resource implements ResourceFactory
throw new IllegalArgumentException(destination+" exists"); throw new IllegalArgumentException(destination+" exists");
writeTo(new FileOutputStream(destination),0,-1); 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.LazyList;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler; import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
@ -212,7 +213,7 @@ public class XmlParser
{ {
if (Log.isDebugEnabled()) if (Log.isDebugEnabled())
Log.debug("parse: " + file); 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(); return new HashSessionIdManager();
} }
public AbstractSessionManager newSessionManager() public SessionManager newSessionManager()
{ {
HashSessionManager manager = new HashSessionManager(); HashSessionManager manager = new HashSessionManager();
manager.setScavengePeriod((int)TimeUnit.SECONDS.toMillis(_scavengePeriod)); 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() * @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionManager()
*/ */
@Override @Override
public AbstractSessionManager newSessionManager() public SessionManager newSessionManager()
{ {
JDBCSessionManager manager = new JDBCSessionManager(); 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 manager.setSaveInterval(SAVE_INTERVAL); //ensure we save any changes to the session at least once per second
return manager; 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(); exchange.waitForDone();
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus()); assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
response = exchange.getResponseContent(); response = exchange.getResponseContent();
assertEquals(response.trim(),String.valueOf(value)); assertEquals(String.valueOf(value),response.trim());
} }
finally finally
{ {
@ -113,7 +113,8 @@ public abstract class AbstractImmortalSessionTest
else if ("get".equals(action)) else if ("get".equals(action))
{ {
HttpSession session = request.getSession(false); HttpSession session = request.getSession(false);
result = (String)session.getAttribute("value"); if (session!=null)
result = (String)session.getAttribute("value");
} }
PrintWriter writer = response.getWriter(); PrintWriter writer = response.getWriter();
writer.println(result); writer.println(result);

View File

@ -109,7 +109,6 @@ public abstract class AbstractLastAccessTimeTest
exchange1.waitForDone(); exchange1.waitForDone();
assertEquals(HttpServletResponse.SC_OK, exchange1.getResponseStatus()); assertEquals(HttpServletResponse.SC_OK, exchange1.getResponseStatus());
// TODO shouldn't the session be expired????
} }
finally finally
{ {
@ -141,7 +140,8 @@ public abstract class AbstractLastAccessTimeTest
else else
{ {
HttpSession session = request.getSession(false); 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"); System.err.println("FINISHED waiting for session to expire");
// Perform one request to server2 to be sure that the session has been expired // 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"); System.err.println("CHECKING NODE2");
ContentExchange exchange2 = new ContentExchange(true); ContentExchange exchange2 = new ContentExchange(true);
@ -123,6 +132,12 @@ public abstract class AbstractOrphanedSessionTest
HttpSession session = request.getSession(true); HttpSession session = request.getSession(true);
session.setAttribute("A", "A"); session.setAttribute("A", "A");
} }
else if ("remove".equals(action))
{
HttpSession session = request.getSession(false);
session.invalidate();
//assertTrue(session == null);
}
else if ("check".equals(action)) else if ("check".equals(action))
{ {
HttpSession session = request.getSession(false); 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 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{ {
HttpSession session = request.getSession(false); HttpSession session = request.getSession(false);
if (session == null) session = request.getSession(true);
String action = request.getParameter("action"); String action = request.getParameter("action");
if ("reenter".equals(action)) if ("reenter".equals(action))
{ {
if (session == null)
session = request.getSession(true);
int port = Integer.parseInt(request.getParameter("port")); int port = Integer.parseInt(request.getParameter("port"));
String path = request.getParameter("path"); String path = request.getParameter("path");
@ -103,10 +104,11 @@ public abstract class AbstractReentrantRequestSessionTest
{ {
ContentExchange exchange = new ContentExchange(true); ContentExchange exchange = new ContentExchange(true);
exchange.setMethod(HttpMethods.GET); 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); client.send(exchange);
exchange.waitForDone(); exchange.waitForDone();
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus()); assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
assertEquals("true",session.getAttribute("reentrant"));
} }
finally finally
{ {
@ -120,7 +122,8 @@ public abstract class AbstractReentrantRequestSessionTest
} }
else 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 static org.junit.Assert.*;
import java.io.IOException; import java.io.IOException;
import java.util.Random;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; 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 SessionIdManager newSessionIdManager();
public abstract AbstractSessionManager newSessionManager(); public abstract SessionManager newSessionManager();
public abstract SessionHandler newSessionHandler(SessionManager sessionManager); public abstract SessionHandler newSessionHandler(SessionManager sessionManager);
@ -70,8 +70,8 @@ public abstract class AbstractTestServer
{ {
ServletContextHandler context = new ServletContextHandler(_contexts, contextPath); ServletContextHandler context = new ServletContextHandler(_contexts, contextPath);
AbstractSessionManager sessionManager = newSessionManager(); SessionManager sessionManager = newSessionManager();
sessionManager.setIdManager(_sessionIdManager); sessionManager.setSessionIdManager(_sessionIdManager);
sessionManager.setMaxInactiveInterval(_maxInactivePeriod); sessionManager.setMaxInactiveInterval(_maxInactivePeriod);
SessionHandler sessionHandler = newSessionHandler(sessionManager); SessionHandler sessionHandler = newSessionHandler(sessionManager);
@ -86,12 +86,17 @@ public abstract class AbstractTestServer
_server.stop(); _server.stop();
} }
public void join() throws Exception
{
_server.join();
}
public WebAppContext addWebAppContext(String warPath, String contextPath) public WebAppContext addWebAppContext(String warPath, String contextPath)
{ {
WebAppContext context = new WebAppContext(_contexts, warPath, contextPath); WebAppContext context = new WebAppContext(_contexts, warPath, contextPath);
AbstractSessionManager sessionManager = newSessionManager(); SessionManager sessionManager = newSessionManager();
sessionManager.setIdManager(_sessionIdManager); sessionManager.setSessionIdManager(_sessionIdManager);
sessionManager.setMaxInactiveInterval(_maxInactivePeriod); sessionManager.setMaxInactiveInterval(_maxInactivePeriod);
SessionHandler sessionHandler = newSessionHandler(sessionManager); SessionHandler sessionHandler = newSessionHandler(sessionManager);