
org.mortbay.jetty.servlet.HashSessionManager Maven / Gradle / Ivy
// ========================================================================
// Copyright 1996-2005 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package org.mortbay.jetty.servlet;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
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.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;
import org.mortbay.log.Log;
import org.mortbay.util.LazyList;
/* ------------------------------------------------------------ */
/** An in-memory implementation of SessionManager.
*
* @author Greg Wilkins (gregw)
*/
public class HashSessionManager extends AbstractSessionManager
{
private static int __id;
private Timer _timer;
private TimerTask _task;
private int _scavengePeriodMs=30000;
private int _savePeriodMs=0; //don't do period saves by default
private TimerTask _saveTask;
protected Map _sessions;
private File _storeDir;
/* ------------------------------------------------------------ */
public HashSessionManager()
{
super();
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see org.mortbay.jetty.servlet.AbstractSessionManager#doStart()
*/
public void doStart() throws Exception
{
_sessions=new ConcurrentHashMap(); // TODO: use syncronizedMap for JDK 1.4
super.doStart();
_timer=new Timer("HashSessionScavenger-"+__id++, true);
setScavengePeriod(getScavengePeriod());
if (_storeDir!=null)
{
if (!_storeDir.exists())
_storeDir.mkdir();
restoreSessions();
}
setSavePeriod(getSavePeriod());
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see org.mortbay.jetty.servlet.AbstractSessionManager#doStop()
*/
public void doStop() throws Exception
{
if (_storeDir != null)
saveSessions();
super.doStop();
_sessions.clear();
_sessions=null;
// stop the scavenger
synchronized(this)
{
if (_saveTask!=null)
_saveTask.cancel();
if (_task!=null)
_task.cancel();
if (_timer!=null)
_timer.cancel();
_timer=null;
}
}
/* ------------------------------------------------------------ */
/**
* @return seconds
*/
public int getScavengePeriod()
{
return _scavengePeriodMs/1000;
}
/* ------------------------------------------------------------ */
public Map getSessionMap()
{
return Collections.unmodifiableMap(_sessions);
}
/* ------------------------------------------------------------ */
public int getSessions()
{
return _sessions.size();
}
/* ------------------------------------------------------------ */
public void setMaxInactiveInterval(int seconds)
{
super.setMaxInactiveInterval(seconds);
if (_dftMaxIdleSecs>0&&_scavengePeriodMs>_dftMaxIdleSecs*1000)
setScavengePeriod((_dftMaxIdleSecs+9)/10);
}
/* ------------------------------------------------------------ */
public void setSavePeriod (int seconds)
{
int oldSavePeriod = _savePeriodMs;
int period = (seconds * 1000);
if (period < 0)
period=0;
_savePeriodMs=period;
if (_timer!=null)
{
synchronized (this)
{
if (_saveTask!=null)
_saveTask.cancel();
if (_savePeriodMs > 0 && _storeDir!=null) //only save if we have a directory configured
{
_saveTask = new TimerTask()
{
public void run()
{
try
{
saveSessions();
}
catch (Exception e)
{
Log.warn(e);
}
}
};
_timer.schedule(_saveTask,_savePeriodMs,_savePeriodMs);
}
}
}
}
/* ------------------------------------------------------------ */
public int getSavePeriod ()
{
if (_savePeriodMs<=0)
return 0;
return _savePeriodMs/1000;
}
/* ------------------------------------------------------------ */
/**
* @param seconds
*/
public void setScavengePeriod(int seconds)
{
if (seconds==0)
seconds=60;
int old_period=_scavengePeriodMs;
int period=seconds*1000;
if (period>60000)
period=60000;
if (period<1000)
period=1000;
_scavengePeriodMs=period;
if (_timer!=null && (period!=old_period || _task==null))
{
synchronized (this)
{
if (_task!=null)
_task.cancel();
_task = new TimerTask()
{
public void run()
{
scavenge();
}
};
_timer.schedule(_task,_scavengePeriodMs,_scavengePeriodMs);
}
}
}
/* -------------------------------------------------------------- */
/**
* Find sessions that have timed out and invalidate them. This runs in the
* SessionScavenger thread.
*/
private void scavenge()
{
//don't attempt to scavenge if we are shutting down
if (isStopping() || isStopped())
return;
Thread thread=Thread.currentThread();
ClassLoader old_loader=thread.getContextClassLoader();
try
{
if (_loader!=null)
thread.setContextClassLoader(_loader);
long now=System.currentTimeMillis();
// Since Hashtable enumeration is not safe over deletes,
// we build a list of stale sessions, then go back and invalidate
// them
Object stale=null;
synchronized (HashSessionManager.this)
{
// For each session
for (Iterator i=_sessions.values().iterator(); i.hasNext();)
{
Session session=(Session)i.next();
long idleTime=session._maxIdleMs;
if (idleTime>0&&session._accessed+idleTime0;)
{
// check it has not been accessed in the meantime
Session session=(Session)LazyList.get(stale,i);
long idleTime=session._maxIdleMs;
if (idleTime>0&&session._accessed+idleTime 0)
{
ArrayList keys = new ArrayList();
for (int i=0; i0&&(_maxIdleMs/10)<_scavengePeriodMs)
HashSessionManager.this.setScavengePeriod((secs+9)/10);
}
/* ------------------------------------------------------------ */
protected Map newAttributeMap()
{
return new HashMap(3);
}
/* ------------------------------------------------------------ */
public void invalidate ()
throws IllegalStateException
{
super.invalidate();
remove();
}
/* ------------------------------------------------------------ */
public void remove()
{
String id=getId();
if (id==null)
return;
//all sessions are invalidated when jetty is stopped, make sure we don't
//remove all the sessions in this case
if (isStopping() || isStopped())
return;
if (_storeDir==null || !_storeDir.exists())
{
return;
}
File f = new File(_storeDir, id);
f.delete();
}
/* ------------------------------------------------------------ */
public 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 (_values != null)
{
out.writeInt(_values.size());
Iterator itor = _values.keySet().iterator();
while (itor.hasNext())
{
String key = (String)itor.next();
out.writeUTF(key);
}
itor = _values.values().iterator();
ObjectOutputStream oos = new ObjectOutputStream(out);
while (itor.hasNext())
{
oos.writeObject(itor.next());
}
oos.close();
}
else
out.writeInt(0);
out.close();
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected class ClassLoadingObjectInputStream extends ObjectInputStream
{
/* ------------------------------------------------------------ */
public ClassLoadingObjectInputStream(java.io.InputStream in) throws IOException
{
super(in);
}
/* ------------------------------------------------------------ */
public ClassLoadingObjectInputStream () throws IOException
{
super();
}
/* ------------------------------------------------------------ */
public Class resolveClass (java.io.ObjectStreamClass cl) throws IOException, ClassNotFoundException
{
try
{
return Class.forName(cl.getName(), false, Thread.currentThread().getContextClassLoader());
}
catch (ClassNotFoundException e)
{
return super.resolveClass(cl);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy