Merge branch 'master' into performance
This commit is contained in:
commit
c61e490d8e
|
@ -1,3 +1,7 @@
|
|||
jetty-7.5.0-SNAPSHOT
|
||||
+ 351516 Refactored sessions to better support nosql session managers
|
||||
+ 351576 Do not use deprecated method File.toURL()
|
||||
|
||||
jetty-7.4.4.v20110707 July 7th 2011
|
||||
+ 308851 Converted all jetty-client module tests to JUnit 4
|
||||
+ 345268 JDBCSessionManager does not work with maxInactiveInterval = -1
|
||||
|
|
|
@ -219,7 +219,7 @@ public class ContextDeployer extends AbstractLifeCycle
|
|||
@Deprecated
|
||||
public void setConfigurationDir(File file) throws Exception
|
||||
{
|
||||
setConfigurationDir(Resource.newResource(file.toURL()));
|
||||
setConfigurationDir(Resource.newResource(Resource.toURL(file)));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -52,7 +52,7 @@ public class MockAppProvider extends AbstractLifeCycle implements AppProvider
|
|||
WebAppContext context = new WebAppContext();
|
||||
|
||||
File war = new File(webappsDir,app.getOriginId().substring(5));
|
||||
context.setWar(Resource.newResource(war.toURI().toURL()).toString());
|
||||
context.setWar(Resource.newResource(Resource.toURL(war)).toString());
|
||||
|
||||
String path = war.getName();
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
|||
import org.eclipse.jetty.toolchain.test.PathAssert;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
import org.junit.Assert;
|
||||
|
@ -132,7 +133,7 @@ public class XmlConfiguredJetty
|
|||
|
||||
public void addConfiguration(File xmlConfigFile) throws MalformedURLException
|
||||
{
|
||||
_xmlConfigurations.add(xmlConfigFile.toURI().toURL());
|
||||
_xmlConfigurations.add(Resource.toURL(xmlConfigFile));
|
||||
}
|
||||
|
||||
public void addConfiguration(String testConfigName) throws MalformedURLException
|
||||
|
|
|
@ -1108,31 +1108,25 @@ public class Request implements HttpServletRequest
|
|||
* @see javax.servlet.http.HttpServletRequest#getSession(boolean)
|
||||
*/
|
||||
public HttpSession getSession(boolean create)
|
||||
{
|
||||
if (_sessionManager==null && create)
|
||||
{
|
||||
if (_session != null )
|
||||
{
|
||||
if (_sessionManager!=null && !_sessionManager.isValid(_session))
|
||||
_session=null;
|
||||
else
|
||||
return _session;
|
||||
}
|
||||
|
||||
if (!create)
|
||||
return null;
|
||||
|
||||
if (_sessionManager==null)
|
||||
throw new IllegalStateException("No SessionManager");
|
||||
|
||||
if (_session != null && _sessionManager!=null && _sessionManager.isValid(_session))
|
||||
return _session;
|
||||
|
||||
_session=null;
|
||||
|
||||
String id=getRequestedSessionId();
|
||||
|
||||
if (id != null && _sessionManager!=null)
|
||||
{
|
||||
_session=_sessionManager.getHttpSession(id);
|
||||
if (_session == null && !create)
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_session == null && _sessionManager!=null && create )
|
||||
{
|
||||
_session=_sessionManager.newHttpSession(this);
|
||||
HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
|
||||
if (cookie!=null)
|
||||
_connection.getResponse().addCookie(cookie);
|
||||
}
|
||||
|
||||
_session=_sessionManager.newHttpSession(this);
|
||||
HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
|
||||
if (cookie!=null)
|
||||
_connection.getResponse().addCookie(cookie);
|
||||
|
||||
return _session;
|
||||
}
|
||||
|
@ -1292,7 +1286,7 @@ public class Request implements HttpServletRequest
|
|||
return false;
|
||||
|
||||
HttpSession session=getSession(false);
|
||||
return (session != null && _sessionManager.getIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
|
||||
return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -187,14 +187,14 @@ public interface SessionManager extends LifeCycle
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the cross context session id manager.
|
||||
* @see #setIdManager(SessionIdManager)
|
||||
* @see #setSessionIdManager(SessionIdManager)
|
||||
*/
|
||||
public SessionIdManager getIdManager();
|
||||
public SessionIdManager getSessionIdManager();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the cross context session id manager.
|
||||
* @deprecated use {@link #getIdManager()}
|
||||
* @deprecated use {@link #getSessionIdManager()}
|
||||
*/
|
||||
@Deprecated
|
||||
public SessionIdManager getMetaManager();
|
||||
|
@ -204,9 +204,9 @@ public interface SessionManager extends LifeCycle
|
|||
* Sets the cross context session id manager
|
||||
*
|
||||
* @param idManager the cross context session id manager.
|
||||
* @see #getIdManager()
|
||||
* @see #getSessionIdManager()
|
||||
*/
|
||||
public void setIdManager(SessionIdManager idManager);
|
||||
public void setSessionIdManager(SessionIdManager idManager);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -15,24 +15,18 @@ package org.eclipse.jetty.server.session;
|
|||
|
||||
import static java.lang.Math.round;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionActivationListener;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
import javax.servlet.http.HttpSessionContext;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
@ -44,9 +38,8 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.SessionIdManager;
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.statistic.CounterStatistic;
|
||||
import org.eclipse.jetty.util.statistic.SampleStatistic;
|
||||
|
||||
|
@ -59,16 +52,29 @@ import org.eclipse.jetty.util.statistic.SampleStatistic;
|
|||
* a specialised version of the Session inner class that provides an attribute
|
||||
* Map.
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
|
||||
{
|
||||
final static Logger __log = SessionHandler.__log;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public final static int __distantFuture=60*60*24*7*52*20;
|
||||
|
||||
private static final HttpSessionContext __nullSessionContext=new NullSessionContext();
|
||||
|
||||
static final HttpSessionContext __nullSessionContext=new HttpSessionContext()
|
||||
{
|
||||
public HttpSession getSession(String sessionId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Enumeration getIds()
|
||||
{
|
||||
return Collections.enumeration(Collections.EMPTY_LIST);
|
||||
}
|
||||
};
|
||||
|
||||
private boolean _usingCookies=true;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -79,8 +85,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
protected boolean _httpOnly=false;
|
||||
protected SessionIdManager _sessionIdManager;
|
||||
protected boolean _secureCookies=false;
|
||||
protected Object _sessionAttributeListeners;
|
||||
protected Object _sessionListeners;
|
||||
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
|
||||
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
|
||||
|
||||
protected ClassLoader _loader;
|
||||
protected ContextHandler.Context _context;
|
||||
|
@ -102,27 +108,40 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ContextHandler.Context getContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ContextHandler getContextHandler()
|
||||
{
|
||||
return _context.getContextHandler();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public HttpCookie access(HttpSession session,boolean secure)
|
||||
{
|
||||
long now=System.currentTimeMillis();
|
||||
|
||||
Session s = ((SessionIf)session).getSession();
|
||||
s.access(now);
|
||||
AbstractSession s = ((SessionIf)session).getSession();
|
||||
|
||||
// Do we need to refresh the cookie?
|
||||
if (isUsingCookies() &&
|
||||
(s.isIdChanged() ||
|
||||
(getMaxCookieAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
|
||||
)
|
||||
)
|
||||
if (s.access(now))
|
||||
{
|
||||
HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure);
|
||||
s.cookieSet();
|
||||
s.setIdChanged(false);
|
||||
return cookie;
|
||||
// Do we need to refresh the cookie?
|
||||
if (isUsingCookies() &&
|
||||
(s.isIdChanged() ||
|
||||
(getMaxCookieAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
|
||||
)
|
||||
)
|
||||
{
|
||||
HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure);
|
||||
s.cookieSet();
|
||||
s.setIdChanged(false);
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -130,22 +149,22 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
public void addEventListener(EventListener listener)
|
||||
{
|
||||
if (listener instanceof HttpSessionAttributeListener)
|
||||
_sessionAttributeListeners=LazyList.add(_sessionAttributeListeners,listener);
|
||||
_sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
|
||||
if (listener instanceof HttpSessionListener)
|
||||
_sessionListeners=LazyList.add(_sessionListeners,listener);
|
||||
_sessionListeners.add((HttpSessionListener)listener);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void clearEventListeners()
|
||||
{
|
||||
_sessionAttributeListeners=null;
|
||||
_sessionListeners=null;
|
||||
_sessionAttributeListeners.clear();
|
||||
_sessionListeners.clear();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void complete(HttpSession session)
|
||||
{
|
||||
Session s = ((SessionIf)session).getSession();
|
||||
AbstractSession s = ((SessionIf)session).getSession();
|
||||
s.complete();
|
||||
}
|
||||
|
||||
|
@ -230,20 +249,29 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
/* ------------------------------------------------------------ */
|
||||
public HttpSession getHttpSession(String nodeId)
|
||||
{
|
||||
String cluster_id = getIdManager().getClusterId(nodeId);
|
||||
String cluster_id = getSessionIdManager().getClusterId(nodeId);
|
||||
|
||||
Session session = getSession(cluster_id);
|
||||
AbstractSession session = getSession(cluster_id);
|
||||
if (session!=null && !session.getNodeId().equals(nodeId))
|
||||
session.setIdChanged(true);
|
||||
return session;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the metaManager used for cross context session management
|
||||
* @deprecated Use {@link #getSessionIdManager()}
|
||||
*/
|
||||
public SessionIdManager getIdManager()
|
||||
{
|
||||
return getSessionIdManager();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the SessionIdManager used for cross context session management
|
||||
*/
|
||||
public SessionIdManager getSessionIdManager()
|
||||
{
|
||||
return _sessionIdManager;
|
||||
}
|
||||
|
@ -293,12 +321,12 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @deprecated use {@link #getIdManager()}
|
||||
* @deprecated use {@link #getSessionIdManager()}
|
||||
*/
|
||||
@Deprecated
|
||||
public SessionIdManager getMetaManager()
|
||||
{
|
||||
return getIdManager();
|
||||
return getSessionIdManager();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -373,7 +401,11 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
/**
|
||||
* @deprecated Need to review if it is needed.
|
||||
*/
|
||||
public abstract Map getSessionMap();
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Map getSessionMap()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getSessionPath()
|
||||
|
@ -411,21 +443,21 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
/* ------------------------------------------------------------ */
|
||||
public boolean isValid(HttpSession session)
|
||||
{
|
||||
Session s = ((SessionIf)session).getSession();
|
||||
AbstractSession s = ((SessionIf)session).getSession();
|
||||
return s.isValid();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getClusterId(HttpSession session)
|
||||
{
|
||||
Session s = ((SessionIf)session).getSession();
|
||||
AbstractSession s = ((SessionIf)session).getSession();
|
||||
return s.getClusterId();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getNodeId(HttpSession session)
|
||||
{
|
||||
Session s = ((SessionIf)session).getSession();
|
||||
AbstractSession s = ((SessionIf)session).getSession();
|
||||
return s.getNodeId();
|
||||
}
|
||||
|
||||
|
@ -435,7 +467,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
*/
|
||||
public HttpSession newHttpSession(HttpServletRequest request)
|
||||
{
|
||||
Session session=newSession(request);
|
||||
AbstractSession session=newSession(request);
|
||||
session.setMaxInactiveInterval(_dftMaxIdleSecs);
|
||||
addSession(session,true);
|
||||
return session;
|
||||
|
@ -445,9 +477,9 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
public void removeEventListener(EventListener listener)
|
||||
{
|
||||
if (listener instanceof HttpSessionAttributeListener)
|
||||
_sessionAttributeListeners=LazyList.remove(_sessionAttributeListeners,listener);
|
||||
_sessionAttributeListeners.remove(listener);
|
||||
if (listener instanceof HttpSessionListener)
|
||||
_sessionListeners=LazyList.remove(_sessionListeners,listener);
|
||||
_sessionListeners.remove(listener);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -480,12 +512,21 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
_httpOnly=httpOnly;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param metaManager The metaManager used for cross context session management.
|
||||
* @deprecated use {@link #setSessionIdManager(SessionIdManager)}
|
||||
*/
|
||||
public void setIdManager(SessionIdManager metaManager)
|
||||
{
|
||||
setSessionIdManager(metaManager);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param metaManager The metaManager used for cross context session management.
|
||||
*/
|
||||
public void setIdManager(SessionIdManager metaManager)
|
||||
public void setSessionIdManager(SessionIdManager metaManager)
|
||||
{
|
||||
_sessionIdManager=metaManager;
|
||||
}
|
||||
|
@ -511,12 +552,12 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @deprecated use {@link #setIdManager(SessionIdManager)}
|
||||
* @deprecated use {@link #setSessionIdManager(SessionIdManager)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setMetaManager(SessionIdManager metaManager)
|
||||
{
|
||||
setIdManager(metaManager);
|
||||
setSessionIdManager(metaManager);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -591,14 +632,14 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
}
|
||||
|
||||
|
||||
protected abstract void addSession(Session session);
|
||||
protected abstract void addSession(AbstractSession session);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Add the session Registers the session with this manager and registers the
|
||||
* session ID with the sessionIDManager;
|
||||
*/
|
||||
protected void addSession(Session session, boolean created)
|
||||
protected void addSession(AbstractSession session, boolean created)
|
||||
{
|
||||
synchronized (_sessionIdManager)
|
||||
{
|
||||
|
@ -612,8 +653,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
if (_sessionListeners!=null)
|
||||
{
|
||||
HttpSessionEvent event=new HttpSessionEvent(session);
|
||||
for (int i=0; i<LazyList.size(_sessionListeners); i++)
|
||||
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionCreated(event);
|
||||
for (HttpSessionListener listener : _sessionListeners)
|
||||
listener.sessionCreated(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -624,7 +665,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
* @param idInCluster The session ID in the cluster, stripped of any worker name.
|
||||
* @return A Session or null if none exists.
|
||||
*/
|
||||
public abstract Session getSession(String idInCluster);
|
||||
public abstract AbstractSession getSession(String idInCluster);
|
||||
|
||||
protected abstract void invalidateSessions() throws Exception;
|
||||
|
||||
|
@ -635,7 +676,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
* @param request
|
||||
* @return the new session
|
||||
*/
|
||||
protected abstract Session newSession(HttpServletRequest request);
|
||||
protected abstract AbstractSession newSession(HttpServletRequest request);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -664,7 +705,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
*/
|
||||
public void removeSession(HttpSession session, boolean invalidate)
|
||||
{
|
||||
Session s = ((SessionIf)session).getSession();
|
||||
AbstractSession s = ((SessionIf)session).getSession();
|
||||
removeSession(s,invalidate);
|
||||
}
|
||||
|
||||
|
@ -674,7 +715,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
|
||||
* {@link SessionIdManager#invalidateAll(String)} should be called.
|
||||
*/
|
||||
public void removeSession(Session session, boolean invalidate)
|
||||
public void removeSession(AbstractSession session, boolean invalidate)
|
||||
{
|
||||
// Remove session from context and global maps
|
||||
boolean removed = removeSession(session.getClusterId());
|
||||
|
@ -692,8 +733,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
if (invalidate && _sessionListeners!=null)
|
||||
{
|
||||
HttpSessionEvent event=new HttpSessionEvent(session);
|
||||
for (int i=LazyList.size(_sessionListeners); i-->0;)
|
||||
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionDestroyed(event);
|
||||
for (HttpSessionListener listener : _sessionListeners)
|
||||
listener.sessionCreated(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -754,41 +795,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
{
|
||||
_checkingRemoteSessionIdEncoding=remote;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Null returning implementation of HttpSessionContext
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static class NullSessionContext implements HttpSessionContext
|
||||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
private NullSessionContext()
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @deprecated From HttpSessionContext
|
||||
*/
|
||||
@Deprecated
|
||||
public Enumeration getIds()
|
||||
{
|
||||
return Collections.enumeration(Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @deprecated From HttpSessionContext
|
||||
*/
|
||||
@Deprecated
|
||||
public HttpSession getSession(String id)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -799,496 +806,23 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
|||
*/
|
||||
public interface SessionIf extends HttpSession
|
||||
{
|
||||
public Session getSession();
|
||||
public AbstractSession getSession();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* Implements {@link javax.servlet.http.HttpSession} from the <code>javax.servlet</code> package.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class Session implements SessionIf, Serializable
|
||||
public void doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value)
|
||||
{
|
||||
protected final String _clusterId; // ID unique within cluster
|
||||
protected final String _nodeId; // ID unique within node
|
||||
protected final Map<String,Object> _attributes=new HashMap<String, Object>();
|
||||
protected boolean _idChanged;
|
||||
protected final long _created;
|
||||
protected long _cookieSet;
|
||||
protected long _accessed;
|
||||
protected long _lastAccessed;
|
||||
protected boolean _invalid;
|
||||
protected boolean _doInvalidate;
|
||||
protected long _maxIdleMs=_dftMaxIdleSecs>0?_dftMaxIdleSecs*1000:-1;
|
||||
protected boolean _newSession;
|
||||
protected int _requests;
|
||||
if (!_sessionAttributeListeners.isEmpty())
|
||||
{
|
||||
HttpSessionBindingEvent event=new HttpSessionBindingEvent(session,name,old==null?value:old);
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected Session(HttpServletRequest request)
|
||||
{
|
||||
_newSession=true;
|
||||
_created=System.currentTimeMillis();
|
||||
_clusterId=_sessionIdManager.newSessionId(request,_created);
|
||||
_nodeId=_sessionIdManager.getNodeId(_clusterId,request);
|
||||
_accessed=_created;
|
||||
_lastAccessed=_created;
|
||||
_requests=1;
|
||||
Log.debug("new session & id "+_nodeId+" "+_clusterId);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected Session(long created, long accessed, String clusterId)
|
||||
{
|
||||
_created=created;
|
||||
_clusterId=clusterId;
|
||||
_nodeId=_sessionIdManager.getNodeId(_clusterId,null);
|
||||
_accessed=accessed;
|
||||
_lastAccessed=accessed;
|
||||
_requests=1;
|
||||
Log.debug("new session "+_nodeId+" "+_clusterId);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/**
|
||||
* @return True is the session is invalid or passivated.
|
||||
*/
|
||||
protected boolean isNotAvailable()
|
||||
{
|
||||
return _invalid;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public Session getSession()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
synchronized (Session.this)
|
||||
for (HttpSessionAttributeListener l : _sessionAttributeListeners)
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
|
||||
return _attributes.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Enumeration getAttributeNames()
|
||||
{
|
||||
synchronized (Session.this)
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
List names=_attributes==null?Collections.EMPTY_LIST:new ArrayList(_attributes.keySet());
|
||||
return Collections.enumeration(names);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public long getCookieSetTime()
|
||||
{
|
||||
return _cookieSet;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public long getCreationTime() throws IllegalStateException
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
return _created;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getId() throws IllegalStateException
|
||||
{
|
||||
return _nodeIdInSessionId?_nodeId:_clusterId;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected String getNodeId()
|
||||
{
|
||||
return _nodeId;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected String getClusterId()
|
||||
{
|
||||
return _clusterId;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public long getLastAccessedTime() throws IllegalStateException
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
return _lastAccessed;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public int getMaxInactiveInterval()
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
return (int)(_maxIdleMs/1000);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see javax.servlet.http.HttpSession#getServletContext()
|
||||
*/
|
||||
public ServletContext getServletContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public HttpSessionContext getSessionContext() throws IllegalStateException
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
return __nullSessionContext;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/**
|
||||
* @deprecated As of Version 2.2, this method is replaced by
|
||||
* {@link #getAttribute}
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getValue(String name) throws IllegalStateException
|
||||
{
|
||||
return getAttribute(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/**
|
||||
* @deprecated As of Version 2.2, this method is replaced by
|
||||
* {@link #getAttributeNames}
|
||||
*/
|
||||
@Deprecated
|
||||
public String[] getValueNames() throws IllegalStateException
|
||||
{
|
||||
synchronized(Session.this)
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
if (_attributes==null)
|
||||
return new String[0];
|
||||
String[] a=new String[_attributes.size()];
|
||||
return (String[])_attributes.keySet().toArray(a);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void access(long time)
|
||||
{
|
||||
synchronized(Session.this)
|
||||
{
|
||||
if (!_invalid)
|
||||
{
|
||||
_newSession=false;
|
||||
_lastAccessed=_accessed;
|
||||
_accessed=time;
|
||||
|
||||
if (_maxIdleMs>0 && _lastAccessed>0 && _lastAccessed + _maxIdleMs < time)
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
else
|
||||
{
|
||||
_requests++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void complete()
|
||||
{
|
||||
synchronized(Session.this)
|
||||
{
|
||||
_requests--;
|
||||
if (_doInvalidate && _requests<=0 )
|
||||
doInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected void timeout() throws IllegalStateException
|
||||
{
|
||||
// remove session from context and invalidate other sessions with same ID.
|
||||
removeSession(this,true);
|
||||
|
||||
// Notify listeners and unbind values
|
||||
synchronized (Session.this)
|
||||
{
|
||||
if (!_invalid)
|
||||
{
|
||||
if (_requests<=0)
|
||||
doInvalidate();
|
||||
else
|
||||
_doInvalidate=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public void invalidate() throws IllegalStateException
|
||||
{
|
||||
// remove session from context and invalidate other sessions with same ID.
|
||||
removeSession(this,true);
|
||||
doInvalidate();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected void doInvalidate() throws IllegalStateException
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.debug("invalidate ",_clusterId);
|
||||
// Notify listeners and unbind values
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
clearAttributes();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// mark as invalid
|
||||
_invalid=true;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected void clearAttributes()
|
||||
{
|
||||
while (_attributes!=null && _attributes.size()>0)
|
||||
{
|
||||
ArrayList keys;
|
||||
synchronized (Session.this)
|
||||
{
|
||||
keys=new ArrayList(_attributes.keySet());
|
||||
}
|
||||
|
||||
Iterator iter=keys.iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
String key=(String)iter.next();
|
||||
|
||||
Object value;
|
||||
synchronized (Session.this)
|
||||
{
|
||||
value=_attributes.remove(key);
|
||||
}
|
||||
unbindValue(key,value);
|
||||
|
||||
if (_sessionAttributeListeners!=null)
|
||||
{
|
||||
HttpSessionBindingEvent event=new HttpSessionBindingEvent(this,key,value);
|
||||
|
||||
for (int i=0; i<LazyList.size(_sessionAttributeListeners); i++)
|
||||
((HttpSessionAttributeListener)LazyList.get(_sessionAttributeListeners,i)).attributeRemoved(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_attributes!=null)
|
||||
_attributes.clear();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public boolean isIdChanged()
|
||||
{
|
||||
return _idChanged;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public boolean isNew() throws IllegalStateException
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
return _newSession;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/**
|
||||
* @deprecated As of Version 2.2, this method is replaced by
|
||||
* {@link #setAttribute}
|
||||
*/
|
||||
@Deprecated
|
||||
public void putValue(java.lang.String name, java.lang.Object value) throws IllegalStateException
|
||||
{
|
||||
setAttribute(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void removeAttribute(String name)
|
||||
{
|
||||
Object old;
|
||||
synchronized(Session.this)
|
||||
{
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
if (_attributes==null)
|
||||
return;
|
||||
|
||||
old=_attributes.remove(name);
|
||||
}
|
||||
|
||||
if (old!=null)
|
||||
{
|
||||
unbindValue(name,old);
|
||||
if (_sessionAttributeListeners!=null)
|
||||
{
|
||||
HttpSessionBindingEvent event=new HttpSessionBindingEvent(this,name,old);
|
||||
|
||||
for (int i=0; i<LazyList.size(_sessionAttributeListeners); i++)
|
||||
((HttpSessionAttributeListener)LazyList.get(_sessionAttributeListeners,i)).attributeRemoved(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/**
|
||||
* @deprecated As of Version 2.2, this method is replaced by
|
||||
* {@link #removeAttribute}
|
||||
*/
|
||||
@Deprecated
|
||||
public void removeValue(java.lang.String name) throws IllegalStateException
|
||||
{
|
||||
removeAttribute(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
Object old_value=null;
|
||||
synchronized (Session.this)
|
||||
{
|
||||
if (value==null)
|
||||
{
|
||||
removeAttribute(name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNotAvailable())
|
||||
throw new IllegalStateException();
|
||||
old_value=_attributes.put(name,value);
|
||||
}
|
||||
|
||||
if (old_value==null || !value.equals(old_value))
|
||||
{
|
||||
unbindValue(name,old_value);
|
||||
bindValue(name,value);
|
||||
|
||||
if (_sessionAttributeListeners!=null)
|
||||
{
|
||||
HttpSessionBindingEvent event=new HttpSessionBindingEvent(this,name,old_value==null?value:old_value);
|
||||
|
||||
for (int i=0; i<LazyList.size(_sessionAttributeListeners); i++)
|
||||
{
|
||||
HttpSessionAttributeListener l=(HttpSessionAttributeListener)LazyList.get(_sessionAttributeListeners,i);
|
||||
|
||||
if (old_value==null)
|
||||
l.attributeAdded(event);
|
||||
else
|
||||
l.attributeReplaced(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public void setIdChanged(boolean changed)
|
||||
{
|
||||
_idChanged=changed;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
public void setMaxInactiveInterval(int secs)
|
||||
{
|
||||
_maxIdleMs=(long)secs*1000;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.getClass().getName()+":"+getId()+"@"+hashCode();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/** If value implements HttpSessionBindingListener, call valueBound() */
|
||||
protected void bindValue(java.lang.String name, Object value)
|
||||
{
|
||||
if (value!=null&&value instanceof HttpSessionBindingListener)
|
||||
((HttpSessionBindingListener)value).valueBound(new HttpSessionBindingEvent(this,name));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected boolean isValid()
|
||||
{
|
||||
return !_invalid;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected void cookieSet()
|
||||
{
|
||||
_cookieSet=_accessed;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/** If value implements HttpSessionBindingListener, call valueUnbound() */
|
||||
protected void unbindValue(java.lang.String name, Object value)
|
||||
{
|
||||
if (value!=null&&value instanceof HttpSessionBindingListener)
|
||||
((HttpSessionBindingListener)value).valueUnbound(new HttpSessionBindingEvent(this,name));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected void willPassivate()
|
||||
{
|
||||
synchronized(Session.this)
|
||||
{
|
||||
HttpSessionEvent event = new HttpSessionEvent(this);
|
||||
for (Iterator iter = _attributes.values().iterator(); iter.hasNext();)
|
||||
{
|
||||
Object value = iter.next();
|
||||
if (value instanceof HttpSessionActivationListener)
|
||||
{
|
||||
HttpSessionActivationListener listener = (HttpSessionActivationListener) value;
|
||||
listener.sessionWillPassivate(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected void didActivate()
|
||||
{
|
||||
synchronized(Session.this)
|
||||
{
|
||||
HttpSessionEvent event = new HttpSessionEvent(this);
|
||||
for (Iterator iter = _attributes.values().iterator(); iter.hasNext();)
|
||||
{
|
||||
Object value = iter.next();
|
||||
if (value instanceof HttpSessionActivationListener)
|
||||
{
|
||||
HttpSessionActivationListener listener = (HttpSessionActivationListener) value;
|
||||
listener.sessionDidActivate(event);
|
||||
}
|
||||
}
|
||||
if (old==null)
|
||||
l.attributeAdded(event);
|
||||
else if (value==null)
|
||||
l.attributeRemoved(event);
|
||||
else
|
||||
l.attributeReplaced(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.server.SessionIdManager;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionManager.Session;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -183,7 +182,7 @@ public class HashSessionIdManager extends AbstractSessionIdManager
|
|||
{
|
||||
for (WeakReference<HttpSession> ref: sessions)
|
||||
{
|
||||
Session session=(Session)ref.get();
|
||||
AbstractSession session=(AbstractSession)ref.get();
|
||||
if (session!=null && session.isValid())
|
||||
session.invalidate();
|
||||
}
|
||||
|
|
|
@ -14,16 +14,11 @@
|
|||
package org.eclipse.jetty.server.session;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
@ -37,8 +32,8 @@ import javax.servlet.ServletContext;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -53,16 +48,18 @@ import org.eclipse.jetty.util.log.Log;
|
|||
*/
|
||||
public class HashSessionManager extends AbstractSessionManager
|
||||
{
|
||||
final static Logger __log = SessionHandler.__log;
|
||||
|
||||
protected final ConcurrentMap<String,HashedSession> _sessions=new ConcurrentHashMap<String,HashedSession>();
|
||||
private static int __id;
|
||||
private Timer _timer;
|
||||
private boolean _timerStop=false;
|
||||
private TimerTask _task;
|
||||
private int _scavengePeriodMs=30000;
|
||||
private int _savePeriodMs=0; //don't do period saves by default
|
||||
private int _idleSavePeriodMs = 0; // don't idle save sessions by default.
|
||||
int _scavengePeriodMs=30000;
|
||||
int _savePeriodMs=0; //don't do period saves by default
|
||||
int _idleSavePeriodMs = 0; // don't idle save sessions by default.
|
||||
private TimerTask _saveTask;
|
||||
private File _storeDir;
|
||||
File _storeDir;
|
||||
private boolean _lazyLoad=false;
|
||||
private volatile boolean _sessionsLoaded=false;
|
||||
|
||||
|
@ -142,24 +139,16 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
return _scavengePeriodMs/1000;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public Map getSessionMap()
|
||||
{
|
||||
return Collections.unmodifiableMap(_sessions);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public int getSessions()
|
||||
{
|
||||
int sessions=super.getSessions();
|
||||
if (Log.isDebugEnabled())
|
||||
if (__log.isDebugEnabled())
|
||||
{
|
||||
if (_sessions.size()!=sessions)
|
||||
Log.warn("sessions: "+_sessions.size()+"!="+sessions);
|
||||
__log.warn("sessions: "+_sessions.size()+"!="+sessions);
|
||||
}
|
||||
return sessions;
|
||||
}
|
||||
|
@ -229,7 +218,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
__log.warn(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -310,13 +299,13 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
for (Iterator<HashedSession> i=_sessions.values().iterator(); i.hasNext();)
|
||||
{
|
||||
HashedSession session=i.next();
|
||||
long idleTime=session._maxIdleMs;
|
||||
if (idleTime>0&&session._accessed+idleTime<now)
|
||||
long idleTime=session.getMaxInactiveInterval()*1000;
|
||||
if (idleTime>0&&session.getAccessed()+idleTime<now)
|
||||
{
|
||||
// Found a stale session, add it to the list
|
||||
session.timeout();
|
||||
}
|
||||
else if (_idleSavePeriodMs>0&&session._accessed+_idleSavePeriodMs<now)
|
||||
else if (_idleSavePeriodMs>0&&session.getAccessed()+_idleSavePeriodMs<now)
|
||||
{
|
||||
session.idle();
|
||||
}
|
||||
|
@ -327,7 +316,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
if (t instanceof ThreadDeath)
|
||||
throw ((ThreadDeath)t);
|
||||
else
|
||||
Log.warn("Problem scavenging sessions", t);
|
||||
__log.warn("Problem scavenging sessions", t);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -337,7 +326,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void addSession(AbstractSessionManager.Session session)
|
||||
protected void addSession(AbstractSession session)
|
||||
{
|
||||
if (isRunning())
|
||||
_sessions.put(session.getClusterId(),(HashedSession)session);
|
||||
|
@ -345,7 +334,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public AbstractSessionManager.Session getSession(String idInCluster)
|
||||
public AbstractSession getSession(String idInCluster)
|
||||
{
|
||||
if ( _lazyLoad && !_sessionsLoaded)
|
||||
{
|
||||
|
@ -355,7 +344,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
__log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,15 +397,15 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected AbstractSessionManager.Session newSession(HttpServletRequest request)
|
||||
protected AbstractSession newSession(HttpServletRequest request)
|
||||
{
|
||||
return new HashedSession(request);
|
||||
return new HashedSession(this, request);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected AbstractSessionManager.Session newSession(long created, long accessed, String clusterId)
|
||||
protected AbstractSession newSession(long created, long accessed, String clusterId)
|
||||
{
|
||||
return new HashedSession(created,accessed, clusterId);
|
||||
return new HashedSession(this, created,accessed, clusterId);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -462,7 +451,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
|
||||
if (!_storeDir.canRead())
|
||||
{
|
||||
Log.warn ("Unable to restore Sessions: Cannot read from Session storage directory "+_storeDir.getAbsolutePath());
|
||||
__log.warn ("Unable to restore Sessions: Cannot read from Session storage directory "+_storeDir.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -492,7 +481,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem restoring session "+idInCuster, e);
|
||||
__log.warn("Problem restoring session "+idInCuster, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -507,7 +496,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
|
||||
if (!_storeDir.canWrite())
|
||||
{
|
||||
Log.warn ("Unable to save Sessions: Session persistence storage directory "+_storeDir.getAbsolutePath()+ " is not writeable");
|
||||
__log.warn ("Unable to save Sessions: Session persistence storage directory "+_storeDir.getAbsolutePath()+ " is not writeable");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -525,23 +514,13 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
DataInputStream in = new DataInputStream(is);
|
||||
String clusterId = in.readUTF();
|
||||
String nodeId = in.readUTF();
|
||||
boolean idChanged = in.readBoolean();
|
||||
long created = in.readLong();
|
||||
long cookieSet = in.readLong();
|
||||
long accessed = in.readLong();
|
||||
long lastAccessed = in.readLong();
|
||||
//boolean invalid = in.readBoolean();
|
||||
//boolean invalidate = in.readBoolean();
|
||||
//long maxIdle = in.readLong();
|
||||
//boolean isNew = in.readBoolean();
|
||||
int requests = in.readInt();
|
||||
|
||||
if (session == null)
|
||||
session = (HashedSession)newSession(created, System.currentTimeMillis(), clusterId);
|
||||
|
||||
session._cookieSet = cookieSet;
|
||||
session._lastAccessed = lastAccessed;
|
||||
|
||||
session = (HashedSession)newSession(created, accessed, clusterId);
|
||||
session.setRequests(requests);
|
||||
int size = in.readInt();
|
||||
if (size>0)
|
||||
{
|
||||
|
@ -560,228 +539,6 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
protected class HashedSession extends Session
|
||||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
private static final long serialVersionUID=-2134521374206116367L;
|
||||
|
||||
/** Whether the session has been saved because it has been deemed idle;
|
||||
* in which case its attribute map will have been saved and cleared. */
|
||||
private transient boolean _idled = false;
|
||||
|
||||
/** Whether there has already been an attempt to save this session
|
||||
* which has failed. If there has, there will be no more save attempts
|
||||
* for this session. This is to stop the logs being flooded with errors
|
||||
* due to serialization failures that are most likely caused by user
|
||||
* data stored in the session that is not serializable. */
|
||||
private transient boolean _saveFailed = false;
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected HashedSession(HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected HashedSession(long created, long accessed, String clusterId)
|
||||
{
|
||||
super(created, accessed, clusterId);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
protected boolean isNotAvailable()
|
||||
{
|
||||
if (_idleSavePeriodMs!=0)
|
||||
deIdle();
|
||||
return _invalid;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
@Override
|
||||
public void setMaxInactiveInterval(int secs)
|
||||
{
|
||||
super.setMaxInactiveInterval(secs);
|
||||
if (_maxIdleMs>0&&(_maxIdleMs/10)<_scavengePeriodMs)
|
||||
HashSessionManager.this.setScavengePeriod((secs+9)/10);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doInvalidate()
|
||||
throws IllegalStateException
|
||||
{
|
||||
super.doInvalidate();
|
||||
|
||||
// Remove from the disk
|
||||
if (_storeDir!=null && getId()!=null)
|
||||
{
|
||||
String id=getId();
|
||||
File f = new File(_storeDir, id);
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private synchronized void save(boolean reactivate)
|
||||
{
|
||||
// Only idle the session if not already idled and no previous save/idle has failed
|
||||
if (!isIdled() && !_saveFailed)
|
||||
{
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Saving {} {}",super.getId(),reactivate);
|
||||
|
||||
File file = null;
|
||||
FileOutputStream fos = null;
|
||||
|
||||
try
|
||||
{
|
||||
file = new File(_storeDir, super.getId());
|
||||
|
||||
if (file.exists())
|
||||
file.delete();
|
||||
file.createNewFile();
|
||||
fos = new FileOutputStream(file);
|
||||
willPassivate();
|
||||
save(fos);
|
||||
if (reactivate)
|
||||
didActivate();
|
||||
else
|
||||
clearAttributes();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
saveFailed(); // We won't try again for this session
|
||||
|
||||
Log.warn("Problem saving session " + super.getId(), e);
|
||||
|
||||
if (fos != null)
|
||||
{
|
||||
// Must not leave the file open if the saving failed
|
||||
IO.close(fos);
|
||||
// No point keeping the file if we didn't save the whole session
|
||||
file.delete();
|
||||
_idled=false; // assume problem was before _values.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
public synchronized void save(OutputStream os) throws IOException
|
||||
{
|
||||
DataOutputStream out = new DataOutputStream(os);
|
||||
out.writeUTF(_clusterId);
|
||||
out.writeUTF(_nodeId);
|
||||
out.writeBoolean(_idChanged);
|
||||
out.writeLong( _created);
|
||||
out.writeLong(_cookieSet);
|
||||
out.writeLong(_accessed);
|
||||
out.writeLong(_lastAccessed);
|
||||
|
||||
/* Don't write these out, as they don't make sense to store because they
|
||||
* either they cannot be true or their value will be restored in the
|
||||
* Session constructor.
|
||||
*/
|
||||
//out.writeBoolean(_invalid);
|
||||
//out.writeBoolean(_doInvalidate);
|
||||
//out.writeLong(_maxIdleMs);
|
||||
//out.writeBoolean( _newSession);
|
||||
out.writeInt(_requests);
|
||||
if (_attributes != null)
|
||||
{
|
||||
out.writeInt(_attributes.size());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(out);
|
||||
for (Map.Entry<String,Object> entry: _attributes.entrySet())
|
||||
{
|
||||
oos.writeUTF(entry.getKey());
|
||||
oos.writeObject(entry.getValue());
|
||||
}
|
||||
oos.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeInt(0);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public synchronized void deIdle()
|
||||
{
|
||||
if (isIdled())
|
||||
{
|
||||
// Access now to prevent race with idling period
|
||||
access(System.currentTimeMillis());
|
||||
|
||||
|
||||
if (Log.isDebugEnabled())
|
||||
{
|
||||
Log.debug("Deidling " + super.getId());
|
||||
}
|
||||
|
||||
FileInputStream fis = null;
|
||||
|
||||
try
|
||||
{
|
||||
File file = new File(_storeDir, super.getId());
|
||||
if (!file.exists() || !file.canRead())
|
||||
throw new FileNotFoundException(file.getName());
|
||||
|
||||
fis = new FileInputStream(file);
|
||||
_idled = false;
|
||||
restoreSession(fis, this);
|
||||
|
||||
didActivate();
|
||||
|
||||
// If we are doing period saves, then there is no point deleting at this point
|
||||
if (_savePeriodMs == 0)
|
||||
file.delete();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem deidling session " + super.getId(), e);
|
||||
IO.close(fis);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Idle the session to reduce session memory footprint.
|
||||
*
|
||||
* The session is idled by persisting it, then clearing the session values attribute map and finally setting
|
||||
* it to an idled state.
|
||||
*/
|
||||
public synchronized void idle()
|
||||
{
|
||||
save(false);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isIdled()
|
||||
{
|
||||
return _idled;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isSaveFailed()
|
||||
{
|
||||
return _saveFailed;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void saveFailed()
|
||||
{
|
||||
_saveFailed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
protected class ClassLoadingObjectInputStream extends ObjectInputStream
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -40,6 +40,7 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
||||
|
||||
|
@ -52,7 +53,9 @@ import org.eclipse.jetty.util.log.Log;
|
|||
*/
|
||||
public class JDBCSessionIdManager extends AbstractSessionIdManager
|
||||
{
|
||||
protected final HashSet<String> _sessionIds = new HashSet();
|
||||
final static Logger __log = SessionHandler.__log;
|
||||
|
||||
protected final HashSet<String> _sessionIds = new HashSet<String>();
|
||||
protected Server _server;
|
||||
protected String _driverClassName;
|
||||
protected String _connectionUrl;
|
||||
|
@ -104,7 +107,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
throws SQLException
|
||||
{
|
||||
_dbName = dbMeta.getDatabaseProductName().toLowerCase();
|
||||
Log.debug ("Using database "+_dbName);
|
||||
__log.debug ("Using database "+_dbName);
|
||||
_isLower = dbMeta.storesLowerCaseIdentifiers();
|
||||
_isUpper = dbMeta.storesUpperCaseIdentifiers();
|
||||
}
|
||||
|
@ -228,7 +231,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
if ((System.currentTimeMillis()%2) == 0)
|
||||
_scavengeIntervalMs += tenPercent;
|
||||
|
||||
if (Log.isDebugEnabled()) Log.debug("Scavenging every "+_scavengeIntervalMs+" ms");
|
||||
if (__log.isDebugEnabled()) __log.debug("Scavenging every "+_scavengeIntervalMs+" ms");
|
||||
if (_timer!=null && (period!=old_period || _task==null))
|
||||
{
|
||||
synchronized (this)
|
||||
|
@ -269,7 +272,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem storing session id="+id, e);
|
||||
__log.warn("Problem storing session id="+id, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -292,8 +295,8 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
|
||||
synchronized (_sessionIds)
|
||||
{
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Removing session id="+id);
|
||||
if (__log.isDebugEnabled())
|
||||
__log.debug("Removing session id="+id);
|
||||
try
|
||||
{
|
||||
_sessionIds.remove(id);
|
||||
|
@ -301,7 +304,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem removing session id="+id, e);
|
||||
__log.warn("Problem removing session id="+id, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,7 +359,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem checking inUse for id="+clusterId, e);
|
||||
__log.warn("Problem checking inUse for id="+clusterId, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -407,13 +410,13 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
initializeDatabase();
|
||||
prepareTables();
|
||||
super.doStart();
|
||||
if (Log.isDebugEnabled()) Log.debug("Scavenging interval = "+getScavengeInterval()+" sec");
|
||||
if (__log.isDebugEnabled()) __log.debug("Scavenging interval = "+getScavengeInterval()+" sec");
|
||||
_timer=new Timer("JDBCSessionScavenger", true);
|
||||
setScavengeInterval(getScavengeInterval());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem initialising JettySessionIds table", e);
|
||||
__log.warn("Problem initialising JettySessionIds table", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -650,7 +653,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
List expiredSessionIds = new ArrayList();
|
||||
try
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Scavenge sweep started at "+System.currentTimeMillis());
|
||||
if (__log.isDebugEnabled()) __log.debug("Scavenge sweep started at "+System.currentTimeMillis());
|
||||
if (_lastScavengeTime > 0)
|
||||
{
|
||||
connection = getConnection();
|
||||
|
@ -659,7 +662,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
PreparedStatement statement = connection.prepareStatement(_selectExpiredSessions);
|
||||
long lowerBound = (_lastScavengeTime - _scavengeIntervalMs);
|
||||
long upperBound = _lastScavengeTime;
|
||||
if (Log.isDebugEnabled()) Log.debug (" Searching for sessions expired between "+lowerBound + " and "+upperBound);
|
||||
if (__log.isDebugEnabled()) __log.debug (" Searching for sessions expired between "+lowerBound + " and "+upperBound);
|
||||
|
||||
statement.setLong(1, lowerBound);
|
||||
statement.setLong(2, upperBound);
|
||||
|
@ -668,7 +671,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
{
|
||||
String sessionId = result.getString("sessionId");
|
||||
expiredSessionIds.add(sessionId);
|
||||
if (Log.isDebugEnabled()) Log.debug (" Found expired sessionId="+sessionId);
|
||||
if (__log.isDebugEnabled()) __log.debug (" Found expired sessionId="+sessionId);
|
||||
}
|
||||
|
||||
//tell the SessionManagers to expire any sessions with a matching sessionId in memory
|
||||
|
@ -691,7 +694,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
upperBound = _lastScavengeTime - (2 * _scavengeIntervalMs);
|
||||
if (upperBound > 0)
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Deleting old expired sessions expired before "+upperBound);
|
||||
if (__log.isDebugEnabled()) __log.debug("Deleting old expired sessions expired before "+upperBound);
|
||||
statement = connection.prepareStatement(_deleteOldExpiredSessions);
|
||||
statement.setLong(1, upperBound);
|
||||
statement.executeUpdate();
|
||||
|
@ -700,12 +703,12 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem selecting expired sessions", e);
|
||||
__log.warn("Problem selecting expired sessions", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lastScavengeTime=System.currentTimeMillis();
|
||||
if (Log.isDebugEnabled()) Log.debug("Scavenge sweep ended at "+_lastScavengeTime);
|
||||
if (__log.isDebugEnabled()) __log.debug("Scavenge sweep ended at "+_lastScavengeTime);
|
||||
if (connection != null)
|
||||
{
|
||||
try
|
||||
|
@ -714,7 +717,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
__log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
_created=System.currentTimeMillis();
|
||||
_accessed = _created;
|
||||
_attributes = new HashMap<String,Object>();
|
||||
_lastNode = getIdManager().getWorkerName();
|
||||
_lastNode = getSessionIdManager().getWorkerName();
|
||||
}
|
||||
|
||||
public SessionData (String sessionId,Map<String,Object> attributes)
|
||||
|
@ -114,7 +114,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
_created=System.currentTimeMillis();
|
||||
_accessed = _created;
|
||||
_attributes = attributes;
|
||||
_lastNode = getIdManager().getWorkerName();
|
||||
_lastNode = getSessionIdManager().getWorkerName();
|
||||
}
|
||||
|
||||
public synchronized String getId ()
|
||||
|
@ -260,7 +260,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
*
|
||||
* Session instance in memory of this node.
|
||||
*/
|
||||
public class Session extends AbstractSessionManager.Session
|
||||
public class Session extends AbstractSession
|
||||
{
|
||||
private static final long serialVersionUID = 5208464051134226143L;
|
||||
private final SessionData _data;
|
||||
|
@ -273,13 +273,14 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
*/
|
||||
protected Session (HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
_data = new SessionData(_clusterId,_attributes);
|
||||
super(JDBCSessionManager.this,request);
|
||||
_data = new SessionData(getClusterId(),_jdbcAttributes);
|
||||
if (_dftMaxIdleSecs>0)
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000);
|
||||
_data.setCanonicalContext(canonicalize(_context.getContextPath()));
|
||||
_data.setVirtualHost(getVirtualHost(_context));
|
||||
_data.setExpiryTime(_maxIdleMs < 0 ? 0 : (System.currentTimeMillis() + _maxIdleMs));
|
||||
int maxInterval=getMaxInactiveInterval();
|
||||
_data.setExpiryTime(maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -288,12 +289,12 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
*/
|
||||
protected Session (long accessed, SessionData data)
|
||||
{
|
||||
super(data.getCreated(), accessed, data.getId());
|
||||
super(JDBCSessionManager.this,data.getCreated(), accessed, data.getId());
|
||||
_data=data;
|
||||
if (_dftMaxIdleSecs>0)
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000);
|
||||
_attributes.putAll(_data.getAttributeMap());
|
||||
_data.setAttributeMap(_attributes);
|
||||
_jdbcAttributes.putAll(_data.getAttributeMap());
|
||||
_data.setAttributeMap(_jdbcAttributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -320,20 +321,26 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
* Entry to session.
|
||||
* Called by SessionHandler on inbound request and the session already exists in this node's memory.
|
||||
*
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionManager.Session#access(long)
|
||||
* @see org.eclipse.jetty.server.session.AbstractSession#access(long)
|
||||
*/
|
||||
@Override
|
||||
protected void access(long time)
|
||||
protected boolean access(long time)
|
||||
{
|
||||
super.access(time);
|
||||
_data.setLastAccessed(_data.getAccessed());
|
||||
_data.setAccessed(time);
|
||||
_data.setExpiryTime(_maxIdleMs < 0 ? 0 : (time + _maxIdleMs));
|
||||
if (super.access(time))
|
||||
{
|
||||
_data.setLastAccessed(_data.getAccessed());
|
||||
_data.setAccessed(time);
|
||||
|
||||
int maxInterval=getMaxInactiveInterval();
|
||||
_data.setExpiryTime(maxInterval <= 0 ? 0 : (time + maxInterval*1000));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit from session
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionManager.Session#complete()
|
||||
* @see org.eclipse.jetty.server.session.AbstractSession#complete()
|
||||
*/
|
||||
@Override
|
||||
protected void complete()
|
||||
|
@ -504,7 +511,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
" lastSaved="+(session==null?0:session._data._lastSaved)+
|
||||
" interval="+(_saveIntervalSec * 1000)+
|
||||
" lastNode="+session._data.getLastNode()+
|
||||
" thisNode="+getIdManager().getWorkerName()+
|
||||
" thisNode="+getSessionIdManager().getWorkerName()+
|
||||
" difference="+(now - session._data._lastSaved));
|
||||
}
|
||||
|
||||
|
@ -526,13 +533,13 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
|
||||
if (data != null)
|
||||
{
|
||||
if (!data.getLastNode().equals(getIdManager().getWorkerName()) || session==null)
|
||||
if (!data.getLastNode().equals(getSessionIdManager().getWorkerName()) || session==null)
|
||||
{
|
||||
//if the session has no expiry, or it is not already expired
|
||||
if (data._expiryTime <= 0 || data._expiryTime > now)
|
||||
{
|
||||
Log.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getIdManager().getWorkerName());
|
||||
data.setLastNode(getIdManager().getWorkerName());
|
||||
Log.debug("getSession("+idInCluster+"): lastNode="+data.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
|
||||
data.setLastNode(getSessionIdManager().getWorkerName());
|
||||
//session last used on a different node, or we don't have it in memory
|
||||
session = new Session(now,data);
|
||||
_sessions.put(idInCluster, session);
|
||||
|
@ -565,17 +572,6 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the sessions as a map of id to Session.
|
||||
*/
|
||||
@Override
|
||||
public Map getSessionMap()
|
||||
{
|
||||
return Collections.unmodifiableMap(_sessions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the number of sessions.
|
||||
|
@ -686,10 +682,10 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
/**
|
||||
* Add a newly created session to our in-memory list for this node and persist it.
|
||||
*
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionManager#addSession(org.eclipse.jetty.server.session.AbstractSessionManager.Session)
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionManager#addSession(org.eclipse.jetty.server.session.AbstractSessionManager.AbstractSession)
|
||||
*/
|
||||
@Override
|
||||
protected void addSession(AbstractSessionManager.Session session)
|
||||
protected void addSession(AbstractSession session)
|
||||
{
|
||||
if (session==null)
|
||||
return;
|
||||
|
@ -720,7 +716,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
* @see org.eclipse.jetty.server.session.AbstractSessionManager#newSession(javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
@Override
|
||||
protected AbstractSessionManager.Session newSession(HttpServletRequest request)
|
||||
protected AbstractSession newSession(HttpServletRequest request)
|
||||
{
|
||||
return new Session(request);
|
||||
}
|
||||
|
@ -732,7 +728,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
* {@link SessionIdManager#invalidateAll(String)} should be called.
|
||||
*/
|
||||
@Override
|
||||
public void removeSession(AbstractSessionManager.Session session, boolean invalidate)
|
||||
public void removeSession(AbstractSession session, boolean invalidate)
|
||||
{
|
||||
// Remove session from context and global maps
|
||||
boolean removed = false;
|
||||
|
@ -755,11 +751,11 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
if (invalidate)
|
||||
_sessionIdManager.invalidateAll(session.getClusterId());
|
||||
|
||||
if (invalidate && _sessionListeners!=null)
|
||||
if (invalidate && !_sessionListeners.isEmpty())
|
||||
{
|
||||
HttpSessionEvent event=new HttpSessionEvent(session);
|
||||
for (int i=LazyList.size(_sessionListeners); i-->0;)
|
||||
((HttpSessionListener)LazyList.get(_sessionListeners,i)).sessionDestroyed(event);
|
||||
for (HttpSessionListener l : _sessionListeners)
|
||||
l.sessionDestroyed(event);
|
||||
}
|
||||
if (!invalidate)
|
||||
{
|
||||
|
@ -883,7 +879,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
data.setCanonicalContext(result.getString("contextPath"));
|
||||
data.setVirtualHost(result.getString("virtualHost"));
|
||||
|
||||
InputStream is = ((JDBCSessionIdManager)getIdManager())._dbAdaptor.getBlobInputStream(result, "map");
|
||||
InputStream is = ((JDBCSessionIdManager)getSessionIdManager())._dbAdaptor.getBlobInputStream(result, "map");
|
||||
ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream (is);
|
||||
Object o = ois.readObject();
|
||||
data.setAttributeMap((Map<String,Object>)o);
|
||||
|
@ -946,7 +942,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
statement.setString(2, data.getId()); //session id
|
||||
statement.setString(3, data.getCanonicalContext()); //context path
|
||||
statement.setString(4, data.getVirtualHost()); //first vhost
|
||||
statement.setString(5, getIdManager().getWorkerName());//my node id
|
||||
statement.setString(5, getSessionIdManager().getWorkerName());//my node id
|
||||
statement.setLong(6, data.getAccessed());//accessTime
|
||||
statement.setLong(7, data.getLastAccessed()); //lastAccessTime
|
||||
statement.setLong(8, data.getCreated()); //time created
|
||||
|
@ -997,7 +993,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
long now = System.currentTimeMillis();
|
||||
connection.setAutoCommit(true);
|
||||
statement = connection.prepareStatement(__updateSession);
|
||||
statement.setString(1, getIdManager().getWorkerName());//my node id
|
||||
statement.setString(1, getSessionIdManager().getWorkerName());//my node id
|
||||
statement.setLong(2, data.getAccessed());//accessTime
|
||||
statement.setLong(3, data.getLastAccessed()); //lastAccessTime
|
||||
statement.setLong(4, now); //last saved time
|
||||
|
@ -1034,7 +1030,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
protected void updateSessionNode (SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
String nodeId = getIdManager().getWorkerName();
|
||||
String nodeId = getSessionIdManager().getWorkerName();
|
||||
Connection connection = getConnection();
|
||||
PreparedStatement statement = null;
|
||||
try
|
||||
|
@ -1071,7 +1067,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
long now = System.currentTimeMillis();
|
||||
connection.setAutoCommit(true);
|
||||
statement = connection.prepareStatement(__updateSessionAccessTime);
|
||||
statement.setString(1, getIdManager().getWorkerName());
|
||||
statement.setString(1, getSessionIdManager().getWorkerName());
|
||||
statement.setLong(2, data.getAccessed());
|
||||
statement.setLong(3, data.getLastAccessed());
|
||||
statement.setLong(4, now);
|
||||
|
@ -1131,7 +1127,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
private Connection getConnection ()
|
||||
throws SQLException
|
||||
{
|
||||
return ((JDBCSessionIdManager)getIdManager()).getConnection();
|
||||
return ((JDBCSessionIdManager)getSessionIdManager()).getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,12 +29,15 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.eclipse.jetty.server.handler.ScopedHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** SessionHandler.
|
||||
*/
|
||||
public class SessionHandler extends ScopedHandler
|
||||
{
|
||||
final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session");
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
private SessionManager _sessionManager;
|
||||
|
||||
|
@ -133,11 +136,9 @@ public class SessionHandler extends ScopedHandler
|
|||
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
setRequestedId(baseRequest,request);
|
||||
|
||||
SessionManager old_session_manager=null;
|
||||
HttpSession old_session=null;
|
||||
|
||||
HttpSession access=null;
|
||||
try
|
||||
{
|
||||
old_session_manager = baseRequest.getSessionManager();
|
||||
|
@ -148,6 +149,7 @@ public class SessionHandler extends ScopedHandler
|
|||
// new session context
|
||||
baseRequest.setSessionManager(_sessionManager);
|
||||
baseRequest.setSession(null);
|
||||
checkRequestedSessionId(baseRequest,request);
|
||||
}
|
||||
|
||||
// access any existing session
|
||||
|
@ -159,6 +161,7 @@ public class SessionHandler extends ScopedHandler
|
|||
{
|
||||
if(session!=old_session)
|
||||
{
|
||||
access=session;
|
||||
HttpCookie cookie = _sessionManager.access(session,request.isSecure());
|
||||
if (cookie!=null ) // Handle changed ID or max-age refresh
|
||||
baseRequest.getResponse().addCookie(cookie);
|
||||
|
@ -172,10 +175,10 @@ public class SessionHandler extends ScopedHandler
|
|||
}
|
||||
}
|
||||
|
||||
if(Log.isDebugEnabled())
|
||||
if(__log.isDebugEnabled())
|
||||
{
|
||||
Log.debug("sessionManager="+_sessionManager);
|
||||
Log.debug("session="+session);
|
||||
__log.debug("sessionManager="+_sessionManager);
|
||||
__log.debug("session="+session);
|
||||
}
|
||||
|
||||
// start manual inline of nextScope(target,baseRequest,request,response);
|
||||
|
@ -190,20 +193,19 @@ public class SessionHandler extends ScopedHandler
|
|||
}
|
||||
finally
|
||||
{
|
||||
HttpSession session=request.getSession(false);
|
||||
|
||||
if (old_session_manager != _sessionManager)
|
||||
if (access!=null)
|
||||
_sessionManager.complete(access);
|
||||
else
|
||||
{
|
||||
//leaving context, free up the session
|
||||
if (session!=null)
|
||||
HttpSession session = baseRequest.getSession(false);
|
||||
if (session!=null && old_session==null)
|
||||
_sessionManager.complete(session);
|
||||
|
||||
// Leave last session in place
|
||||
if (old_session_manager!=null )
|
||||
{
|
||||
baseRequest.setSessionManager(old_session_manager);
|
||||
baseRequest.setSession(old_session);
|
||||
}
|
||||
}
|
||||
|
||||
if (old_session_manager!=null && old_session_manager != _sessionManager)
|
||||
{
|
||||
baseRequest.setSessionManager(old_session_manager);
|
||||
baseRequest.setSession(old_session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,13 +233,22 @@ public class SessionHandler extends ScopedHandler
|
|||
* @param baseRequest
|
||||
* @param request
|
||||
*/
|
||||
protected void setRequestedId(Request baseRequest, HttpServletRequest request)
|
||||
protected void checkRequestedSessionId(Request baseRequest, HttpServletRequest request)
|
||||
{
|
||||
String requested_session_id=request.getRequestedSessionId();
|
||||
if (!DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()) || requested_session_id!=null)
|
||||
|
||||
SessionManager sessionManager = getSessionManager();
|
||||
|
||||
if (requested_session_id!=null && sessionManager!=null)
|
||||
{
|
||||
HttpSession session=sessionManager.getHttpSession(requested_session_id);
|
||||
if (session!=null && sessionManager.isValid(session))
|
||||
baseRequest.setSession(session);
|
||||
return;
|
||||
}
|
||||
else if (!DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
return;
|
||||
|
||||
SessionManager sessionManager = getSessionManager();
|
||||
boolean requested_session_id_from_cookie=false;
|
||||
HttpSession session=null;
|
||||
|
||||
|
@ -251,22 +262,13 @@ public class SessionHandler extends ScopedHandler
|
|||
{
|
||||
if (sessionManager.getSessionCookie().equalsIgnoreCase(cookies[i].getName()))
|
||||
{
|
||||
if (requested_session_id!=null)
|
||||
{
|
||||
// Multiple jsessionid cookies. Probably due to
|
||||
// multiple paths and/or domains. Pick the first
|
||||
// known session or the last defined cookie.
|
||||
if (sessionManager.getHttpSession(requested_session_id)!=null)
|
||||
break;
|
||||
}
|
||||
|
||||
requested_session_id=cookies[i].getValue();
|
||||
requested_session_id_from_cookie = true;
|
||||
if(Log.isDebugEnabled())Log.debug("Got Session ID "+requested_session_id+" from cookie");
|
||||
if(__log.isDebugEnabled())__log.debug("Got Session ID "+requested_session_id+" from cookie");
|
||||
|
||||
session=sessionManager.getHttpSession(requested_session_id);
|
||||
if (session!=null)
|
||||
baseRequest.setSession(session);
|
||||
if (session!=null && sessionManager.isValid(session))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,14 +296,17 @@ public class SessionHandler extends ScopedHandler
|
|||
|
||||
requested_session_id = uri.substring(s,i);
|
||||
requested_session_id_from_cookie = false;
|
||||
if(Log.isDebugEnabled())
|
||||
Log.debug("Got Session ID "+requested_session_id+" from URL");
|
||||
session=sessionManager.getHttpSession(requested_session_id);
|
||||
if(__log.isDebugEnabled())
|
||||
__log.debug("Got Session ID "+requested_session_id+" from URL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baseRequest.setRequestedSessionId(requested_session_id);
|
||||
baseRequest.setRequestedSessionIdFromCookie(requested_session_id!=null && requested_session_id_from_cookie);
|
||||
baseRequest.setRequestedSessionIdFromCookie(requested_session_id!=null && requested_session_id_from_cookie);
|
||||
if (session!=null && sessionManager.isValid(session))
|
||||
baseRequest.setSession(session);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -23,10 +23,9 @@ import java.io.IOException;
|
|||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
@ -49,17 +48,13 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
|
||||
private static int __length = __content.length();
|
||||
|
||||
private StringBuffer _response;
|
||||
private boolean _continue;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Test
|
||||
public void testCloseBetweenRequests() throws Exception
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
_continue = true;
|
||||
_response = new StringBuffer();
|
||||
int maxLength = 32;
|
||||
int requestCount = iterations(maxLength);
|
||||
final CountDownLatch latch = new CountDownLatch(requestCount);
|
||||
|
||||
configureServer(new HelloWorldHandler());
|
||||
|
||||
|
@ -68,17 +63,36 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
{
|
||||
OutputStream os = client.getOutputStream();
|
||||
|
||||
ResponseReader reader = new ResponseReader(client);
|
||||
ResponseReader reader = new ResponseReader(client) {
|
||||
private int _index = 0;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected int doRead() throws IOException, InterruptedException
|
||||
{
|
||||
int count = super.doRead();
|
||||
if (count > 0)
|
||||
{
|
||||
int idx;
|
||||
while ((idx=_response.indexOf("HTTP/1.1 200 OK", _index)) >= 0)
|
||||
{
|
||||
latch.countDown();
|
||||
_index = idx + 15;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
Thread runner = new Thread(reader);
|
||||
runner.start();
|
||||
|
||||
for (int pipeline = 1; pipeline < 32; pipeline++)
|
||||
for (int pipeline = 1; pipeline < maxLength; pipeline++)
|
||||
{
|
||||
if (pipeline == 16)
|
||||
if (pipeline == maxLength / 2)
|
||||
_connector.close();
|
||||
|
||||
total += pipeline;
|
||||
|
||||
String request = "";
|
||||
for (int i = 0; i < pipeline; i++)
|
||||
{
|
||||
|
@ -93,38 +107,32 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
os.write(request.getBytes());
|
||||
os.flush();
|
||||
|
||||
Thread.sleep(50);
|
||||
Thread.sleep(25);
|
||||
}
|
||||
|
||||
_continue = false;
|
||||
latch.await(30, TimeUnit.SECONDS);
|
||||
|
||||
reader.setDone();
|
||||
runner.join();
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
|
||||
int count = 0;
|
||||
StringTokenizer lines = new StringTokenizer(_response.toString(),"\r\n");
|
||||
while(lines.hasMoreTokens())
|
||||
{
|
||||
String line = lines.nextToken();
|
||||
if (line.equals("HTTP/1.1 200 OK"))
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(total, count);
|
||||
assertEquals(requestCount, requestCount - latch.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private int iterations(int cnt)
|
||||
{
|
||||
return cnt > 0 ? iterations(--cnt) + cnt : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Test
|
||||
public void testCloseBetweenChunks() throws Exception
|
||||
{
|
||||
_continue = true;
|
||||
_response = new StringBuffer();
|
||||
|
||||
configureServer(new EchoHandler());
|
||||
|
||||
Socket client = newSocket(HOST,_connector.getLocalPort());
|
||||
|
@ -136,7 +144,6 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
Thread runner = new Thread(reader);
|
||||
runner.start();
|
||||
|
||||
String content = "abcdefghij";
|
||||
byte[] bytes = __content.getBytes("utf-8");
|
||||
|
||||
os.write((
|
||||
|
@ -154,6 +161,7 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
{
|
||||
os.write(bytes, offset, 64);
|
||||
offset += 64;
|
||||
Thread.sleep(25);
|
||||
}
|
||||
|
||||
_connector.close();
|
||||
|
@ -162,15 +170,14 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
{
|
||||
os.write(bytes, offset, len-offset <=64 ? len-offset : 64);
|
||||
offset += 64;
|
||||
Thread.sleep(25);
|
||||
}
|
||||
os.flush();
|
||||
|
||||
Thread.sleep(50);
|
||||
|
||||
_continue = false;
|
||||
reader.setDone();
|
||||
runner.join();
|
||||
|
||||
String in = _response.toString();
|
||||
String in = reader.getResponse().toString();
|
||||
assertTrue(in.indexOf(__content.substring(__length-64))>0);
|
||||
}
|
||||
finally
|
||||
|
@ -183,38 +190,44 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
/* ------------------------------------------------------------ */
|
||||
public class ResponseReader implements Runnable
|
||||
{
|
||||
private BufferedReader _reader;
|
||||
private int _last = 0;
|
||||
private boolean _done = false;
|
||||
|
||||
protected char[] _buffer;
|
||||
protected StringBuffer _response;
|
||||
protected BufferedReader _reader;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ResponseReader(Socket client) throws IOException
|
||||
{
|
||||
_buffer = new char[256];
|
||||
_response = new StringBuffer();
|
||||
_reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setDone()
|
||||
{
|
||||
_done = true;
|
||||
}
|
||||
|
||||
public StringBuffer getResponse()
|
||||
{
|
||||
return _response;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
int count = 0;
|
||||
char[] buffer = new char[256];
|
||||
|
||||
try
|
||||
{
|
||||
while (_continue)
|
||||
int count = 0;
|
||||
while (!_done || _last > 0 || count > 0)
|
||||
{
|
||||
if (_reader.ready())
|
||||
{
|
||||
count = _reader.read(buffer);
|
||||
_response.append(buffer, 0, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
count = doRead();
|
||||
}
|
||||
}
|
||||
catch (IOException ex) { }
|
||||
|
@ -228,5 +241,29 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
|
|||
catch (IOException e) { }
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected int doRead() throws IOException, InterruptedException
|
||||
{
|
||||
if (_last > 0)
|
||||
{
|
||||
_last = 0;
|
||||
|
||||
Thread.sleep(25);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
if (_reader.ready())
|
||||
{
|
||||
count = _reader.read(_buffer);
|
||||
if (count > 0)
|
||||
{
|
||||
_last = count;
|
||||
_response.append(_buffer, 0, count);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.jetty.io.ByteArrayEndPoint;
|
|||
import org.eclipse.jetty.server.bio.SocketConnector;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.session.AbstractSession;
|
||||
import org.eclipse.jetty.server.session.AbstractSessionManager;
|
||||
import org.eclipse.jetty.server.session.HashSessionIdManager;
|
||||
import org.eclipse.jetty.server.session.HashSessionManager;
|
||||
|
@ -330,7 +331,7 @@ public class ResponseTest
|
|||
request.setRequestedSessionId("12345");
|
||||
request.setRequestedSessionIdFromCookie(false);
|
||||
AbstractSessionManager manager=new HashSessionManager();
|
||||
manager.setIdManager(new HashSessionIdManager());
|
||||
manager.setSessionIdManager(new HashSessionIdManager());
|
||||
request.setSessionManager(manager);
|
||||
request.setSession(new TestSession(manager,"12345"));
|
||||
|
||||
|
@ -378,7 +379,7 @@ public class ResponseTest
|
|||
request.setRequestedSessionId("12345");
|
||||
request.setRequestedSessionIdFromCookie(false);
|
||||
AbstractSessionManager manager=new HashSessionManager();
|
||||
manager.setIdManager(new HashSessionIdManager());
|
||||
manager.setSessionIdManager(new HashSessionIdManager());
|
||||
request.setSessionManager(manager);
|
||||
request.setSession(new TestSession(manager,"12345"));
|
||||
manager.setCheckingRemoteSessionIdEncoding(false);
|
||||
|
@ -471,11 +472,11 @@ public class ResponseTest
|
|||
return response;
|
||||
}
|
||||
|
||||
private class TestSession extends AbstractSessionManager.Session
|
||||
private class TestSession extends AbstractSession
|
||||
{
|
||||
public TestSession(AbstractSessionManager abstractSessionManager, String id)
|
||||
{
|
||||
abstractSessionManager.super(System.currentTimeMillis(),System.currentTimeMillis(), id);
|
||||
super(abstractSessionManager, System.currentTimeMillis(),System.currentTimeMillis(), id);
|
||||
}
|
||||
|
||||
public Object getAttribute(String name)
|
||||
|
|
|
@ -271,7 +271,7 @@ public class ContextHandlerTest
|
|||
ContextHandler handler = new ContextHandler();
|
||||
|
||||
assertTrue("Not a directory " + testDirectory,testDirectory.isDirectory());
|
||||
handler.setBaseResource(Resource.newResource(testDirectory.toURI().toURL()));
|
||||
handler.setBaseResource(Resource.newResource(Resource.toURL(testDirectory)));
|
||||
|
||||
List<String> paths = new ArrayList<String>(handler.getResourcePaths(root));
|
||||
assertEquals(2,paths.size());
|
||||
|
|
|
@ -60,7 +60,7 @@ public class SessionHandlerTest
|
|||
return cookieName;
|
||||
}
|
||||
});
|
||||
sessionHandler.setRequestedId(baseRequest,httpRequest);
|
||||
sessionHandler.checkRequestedSessionId(baseRequest,httpRequest);
|
||||
|
||||
assertEquals(sessionId,baseRequest.getRequestedSessionId());
|
||||
assertTrue(baseRequest.isRequestedSessionIdFromCookie());
|
||||
|
@ -100,7 +100,7 @@ public class SessionHandlerTest
|
|||
}
|
||||
});
|
||||
|
||||
sessionHandler.setRequestedId(baseRequest,httpRequest);
|
||||
sessionHandler.checkRequestedSessionId(baseRequest,httpRequest);
|
||||
|
||||
assertEquals(sessionId,baseRequest.getRequestedSessionId());
|
||||
assertFalse(baseRequest.isRequestedSessionIdFromCookie());
|
||||
|
@ -417,7 +417,7 @@ public class SessionHandlerTest
|
|||
return null;
|
||||
}
|
||||
|
||||
public SessionIdManager getIdManager()
|
||||
public SessionIdManager getSessionIdManager()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -496,7 +496,7 @@ public class SessionHandlerTest
|
|||
{
|
||||
}
|
||||
|
||||
public void setIdManager(SessionIdManager idManager)
|
||||
public void setSessionIdManager(SessionIdManager idManager)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ public class Classpath {
|
|||
URL[] urls = new URL[cnt];
|
||||
for (int i=0; i < cnt; i++) {
|
||||
try {
|
||||
String u=((_elements.elementAt(i))).toURL().toString();
|
||||
String u=_elements.elementAt(i).toURI().toURL().toString();
|
||||
urls[i] = new URL(encodeFileURL(u));
|
||||
} catch (MalformedURLException e) {}
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ public class FileResource extends URLResource
|
|||
String can=_file.getCanonicalPath();
|
||||
|
||||
if (abs.length()!=can.length() || !abs.equals(can))
|
||||
_alias=new File(can).toURI().toURL();
|
||||
_alias=Resource.toURL(new File(can));
|
||||
|
||||
_aliasChecked=true;
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ public abstract class Resource implements ResourceFactory
|
|||
resource=resource.substring(2);
|
||||
|
||||
File file=new File(resource).getCanonicalFile();
|
||||
url=file.toURI().toURL();
|
||||
url=Resource.toURL(file);
|
||||
|
||||
URLConnection connection=url.openConnection();
|
||||
connection.setUseCaches(useCaches);
|
||||
|
@ -642,5 +642,15 @@ public abstract class Resource implements ResourceFactory
|
|||
throw new IllegalArgumentException(destination+" exists");
|
||||
writeTo(new FileOutputStream(destination),0,-1);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Generate a properly encoded URL from a {@link File} instance.
|
||||
* @param file Target file.
|
||||
* @return URL of the target file.
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public static URL toURL(File file) throws MalformedURLException
|
||||
{
|
||||
return file.toURI().toURL();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import javax.xml.parsers.SAXParserFactory;
|
|||
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
|
@ -212,7 +213,7 @@ public class XmlParser
|
|||
{
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("parse: " + file);
|
||||
return parse(new InputSource(file.toURL().toString()));
|
||||
return parse(new InputSource(Resource.toURL(file).toString()));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -41,7 +41,7 @@ public class HashTestServer extends AbstractTestServer
|
|||
return new HashSessionIdManager();
|
||||
}
|
||||
|
||||
public AbstractSessionManager newSessionManager()
|
||||
public SessionManager newSessionManager()
|
||||
{
|
||||
HashSessionManager manager = new HashSessionManager();
|
||||
manager.setScavengePeriod((int)TimeUnit.SECONDS.toMillis(_scavengePeriod));
|
||||
|
|
|
@ -76,10 +76,10 @@ public class JdbcTestServer extends AbstractTestServer
|
|||
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionManager()
|
||||
*/
|
||||
@Override
|
||||
public AbstractSessionManager newSessionManager()
|
||||
public SessionManager newSessionManager()
|
||||
{
|
||||
JDBCSessionManager manager = new JDBCSessionManager();
|
||||
manager.setIdManager((JDBCSessionIdManager)_sessionIdManager);
|
||||
manager.setSessionIdManager((JDBCSessionIdManager)_sessionIdManager);
|
||||
manager.setSaveInterval(SAVE_INTERVAL); //ensure we save any changes to the session at least once per second
|
||||
return manager;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -83,7 +83,7 @@ public abstract class AbstractImmortalSessionTest
|
|||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
response = exchange.getResponseContent();
|
||||
assertEquals(response.trim(),String.valueOf(value));
|
||||
assertEquals(String.valueOf(value),response.trim());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -113,7 +113,8 @@ public abstract class AbstractImmortalSessionTest
|
|||
else if ("get".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
result = (String)session.getAttribute("value");
|
||||
if (session!=null)
|
||||
result = (String)session.getAttribute("value");
|
||||
}
|
||||
PrintWriter writer = response.getWriter();
|
||||
writer.println(result);
|
||||
|
|
|
@ -109,7 +109,6 @@ public abstract class AbstractLastAccessTimeTest
|
|||
exchange1.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK, exchange1.getResponseStatus());
|
||||
|
||||
// TODO shouldn't the session be expired????
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -141,7 +140,8 @@ public abstract class AbstractLastAccessTimeTest
|
|||
else
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
session.setAttribute("test", "test");
|
||||
if (session!=null)
|
||||
session.setAttribute("test", "test");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,15 @@ public abstract class AbstractOrphanedSessionTest
|
|||
|
||||
System.err.println("FINISHED waiting for session to expire");
|
||||
// Perform one request to server2 to be sure that the session has been expired
|
||||
//
|
||||
|
||||
// force invalidate to test
|
||||
// ContentExchange exchange3 = new ContentExchange(true);
|
||||
// exchange3.setMethod(HttpMethods.GET);
|
||||
// exchange3.setURL("http://localhost:" + port2 + contextPath + servletMapping + "?action=remove");
|
||||
// exchange3.getRequestFields().add("Cookie", sessionCookie);
|
||||
// client.send(exchange3);
|
||||
// exchange3.waitForDone();
|
||||
|
||||
System.err.println("CHECKING NODE2");
|
||||
ContentExchange exchange2 = new ContentExchange(true);
|
||||
|
@ -123,6 +132,12 @@ public abstract class AbstractOrphanedSessionTest
|
|||
HttpSession session = request.getSession(true);
|
||||
session.setAttribute("A", "A");
|
||||
}
|
||||
else if ("remove".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
session.invalidate();
|
||||
//assertTrue(session == null);
|
||||
}
|
||||
else if ("check".equals(action))
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
|
|
|
@ -83,11 +83,12 @@ public abstract class AbstractReentrantRequestSessionTest
|
|||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) session = request.getSession(true);
|
||||
|
||||
String action = request.getParameter("action");
|
||||
if ("reenter".equals(action))
|
||||
{
|
||||
if (session == null)
|
||||
session = request.getSession(true);
|
||||
int port = Integer.parseInt(request.getParameter("port"));
|
||||
String path = request.getParameter("path");
|
||||
|
||||
|
@ -103,10 +104,11 @@ public abstract class AbstractReentrantRequestSessionTest
|
|||
{
|
||||
ContentExchange exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
exchange.setURL("http://localhost:" + port + path + "?action=none");
|
||||
exchange.setURL("http://localhost:" + port + path + ";jsessionid="+session.getId()+"?action=none");
|
||||
client.send(exchange);
|
||||
exchange.waitForDone();
|
||||
assertEquals(HttpServletResponse.SC_OK,exchange.getResponseStatus());
|
||||
assertEquals("true",session.getAttribute("reentrant"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -120,7 +122,8 @@ public abstract class AbstractReentrantRequestSessionTest
|
|||
}
|
||||
else
|
||||
{
|
||||
// Reentrancy was successful, just return
|
||||
assertTrue(session!=null);
|
||||
session.setAttribute("reentrant","true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.eclipse.jetty.server.session;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -50,7 +50,7 @@ public abstract class AbstractTestServer
|
|||
|
||||
|
||||
public abstract SessionIdManager newSessionIdManager();
|
||||
public abstract AbstractSessionManager newSessionManager();
|
||||
public abstract SessionManager newSessionManager();
|
||||
public abstract SessionHandler newSessionHandler(SessionManager sessionManager);
|
||||
|
||||
|
||||
|
@ -70,8 +70,8 @@ public abstract class AbstractTestServer
|
|||
{
|
||||
ServletContextHandler context = new ServletContextHandler(_contexts, contextPath);
|
||||
|
||||
AbstractSessionManager sessionManager = newSessionManager();
|
||||
sessionManager.setIdManager(_sessionIdManager);
|
||||
SessionManager sessionManager = newSessionManager();
|
||||
sessionManager.setSessionIdManager(_sessionIdManager);
|
||||
sessionManager.setMaxInactiveInterval(_maxInactivePeriod);
|
||||
|
||||
SessionHandler sessionHandler = newSessionHandler(sessionManager);
|
||||
|
@ -86,12 +86,17 @@ public abstract class AbstractTestServer
|
|||
_server.stop();
|
||||
}
|
||||
|
||||
public void join() throws Exception
|
||||
{
|
||||
_server.join();
|
||||
}
|
||||
|
||||
public WebAppContext addWebAppContext(String warPath, String contextPath)
|
||||
{
|
||||
WebAppContext context = new WebAppContext(_contexts, warPath, contextPath);
|
||||
|
||||
AbstractSessionManager sessionManager = newSessionManager();
|
||||
sessionManager.setIdManager(_sessionIdManager);
|
||||
SessionManager sessionManager = newSessionManager();
|
||||
sessionManager.setSessionIdManager(_sessionIdManager);
|
||||
sessionManager.setMaxInactiveInterval(_maxInactivePeriod);
|
||||
|
||||
SessionHandler sessionHandler = newSessionHandler(sessionManager);
|
||||
|
|
Loading…
Reference in New Issue