|
Jetty example source code file (HashSessionManager.java)
The Jetty HashSessionManager.java source code// ======================================================================== // 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.ObjectInputStream; import java.io.ObjectOutputStream; 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 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 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 HashMap(); super.doStart(); _timer=new Timer(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+idleTime<now) { // Found a stale session, add it to the list stale=LazyList.add(stale,session); } } } // Remove the stale sessions for (int i=LazyList.size(stale); i-->0;) { // 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<System.currentTimeMillis()) { ((Session)session).timeout(); int nbsess=this._sessions.size(); if (nbsess<this._minSessions) this._minSessions=nbsess; } } } catch (Throwable t) { if (t instanceof ThreadDeath) throw ((ThreadDeath)t); else Log.warn("Problem scavenging sessions", t); } finally { thread.setContextClassLoader(old_loader); } } /* ------------------------------------------------------------ */ protected void addSession(AbstractSessionManager.Session session) { _sessions.put(session.getClusterId(),session); } /* ------------------------------------------------------------ */ public AbstractSessionManager.Session getSession(String idInCluster) { if (_sessions==null) return null; return (Session)_sessions.get(idInCluster); } /* ------------------------------------------------------------ */ protected void invalidateSessions() { // Invalidate all sessions to cause unbind events ArrayList sessions=new ArrayList(_sessions.values()); for (Iterator i=sessions.iterator(); i.hasNext();) { Session session=(Session)i.next(); session.invalidate(); } _sessions.clear(); } /* ------------------------------------------------------------ */ protected AbstractSessionManager.Session newSession(HttpServletRequest request) { return new Session(request); } /* ------------------------------------------------------------ */ protected void removeSession(String clusterId) { _sessions.remove(clusterId); } public void setStoreDirectory (File dir) { _storeDir=dir; } public File getStoreDirectory () { return _storeDir; } public void restoreSessions () throws Exception { if (_storeDir==null || !_storeDir.exists()) { return; } if (!_storeDir.canRead()) { Log.warn ("Unable to restore Sessions: Cannot read from Session storage directory "+_storeDir.getAbsolutePath()); return; } File[] files = _storeDir.listFiles(); for (int i=0;files!=null&&i<files.length;i++) { try { FileInputStream in = new FileInputStream(files[i]); Session session = restoreSession(in); in.close(); addSession(session, false); files[i].delete(); } catch (Exception e) { Log.warn("Problem restoring session "+files[i].getName(), e); } } } public void saveSessions () throws Exception { if (_storeDir==null || !_storeDir.exists()) { return; } if (!_storeDir.canWrite()) { Log.warn ("Unable to save Sessions: Session persistence storage directory "+_storeDir.getAbsolutePath()+ " is not writeable"); return; } synchronized (this) { Iterator itor = _sessions.entrySet().iterator(); while (itor.hasNext()) { Map.Entry entry = (Map.Entry)itor.next(); String id = (String)entry.getKey(); Session session = (Session)entry.getValue(); try { File file = new File (_storeDir, id); if (file.exists()) file.delete(); file.createNewFile(); FileOutputStream fos = new FileOutputStream (file); session.save(fos); fos.close(); } catch (Exception e) { Log.warn("Problem persisting session "+id, e); } } } } public Session restoreSession (FileInputStream fis) throws Exception { /* * Take care of this class's fields first by calling * defaultReadObject */ DataInputStream in = new DataInputStream(fis); 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(); Session session = new Session (created, clusterId); session._cookieSet = cookieSet; session._lastAccessed = lastAccessed; int size = in.readInt(); if (size > 0) { ArrayList keys = new ArrayList(); for (int i=0; i<size; i++) { String key = in.readUTF(); keys.add(key); } ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(in); for (int i=0;i<size;i++) { Object value = ois.readObject(); session.setAttribute((String)keys.get(i),value); } ois.close(); } else session.initValues(); in.close(); return session; } /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ protected class Session extends AbstractSessionManager.Session { /* ------------------------------------------------------------ */ private static final long serialVersionUID=-2134521374206116367L; /* ------------------------------------------------------------- */ protected Session(HttpServletRequest request) { super(request); } protected Session(long created, String clusterId) { super(created, clusterId); } /* ------------------------------------------------------------- */ public void setMaxInactiveInterval(int secs) { super.setMaxInactiveInterval(secs); if (_maxIdleMs>0&&(_maxIdleMs/10)<_scavengePeriodMs) HashSessionManager.this.setScavengePeriod((secs+9)/10); } /* ------------------------------------------------------------ */ protected Map newAttributeMap() { return new HashMap(3); } public void invalidate () throws IllegalStateException { super.invalidate(); remove(getId()); } public void remove (String id) { 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(FileOutputStream fos) throws IOException { DataOutputStream out = new DataOutputStream(fos); 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 { Class clazz; try { return Thread.currentThread().getContextClassLoader().loadClass(cl.getName()); } catch (ClassNotFoundException e) { return super.resolveClass(cl); } } } } Other Jetty examples (source code examples)Here is a short list of links related to this Jetty HashSessionManager.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.