433244 Session manager lifecycle cleanup
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
index f76df68..1f966c5 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
@@ -26,7 +26,6 @@
 import java.util.EventListener;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -49,7 +48,7 @@
 import org.eclipse.jetty.util.annotation.ManagedAttribute;
 import org.eclipse.jetty.util.annotation.ManagedObject;
 import org.eclipse.jetty.util.annotation.ManagedOperation;
-import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.eclipse.jetty.util.component.ContainerLifeCycle;
 import org.eclipse.jetty.util.log.Logger;
 import org.eclipse.jetty.util.statistic.CounterStatistic;
 import org.eclipse.jetty.util.statistic.SampleStatistic;
@@ -66,7 +65,7 @@
  */
 @SuppressWarnings("deprecation")
 @ManagedObject("Abstract Session Manager")
-public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
+public abstract class AbstractSessionManager extends ContainerLifeCycle implements SessionManager
 {
     final static Logger __log = SessionHandler.LOG;
 
@@ -82,11 +81,13 @@
 
     static final HttpSessionContext __nullSessionContext=new HttpSessionContext()
     {
+        @Override
         public HttpSession getSession(String sessionId)
         {
             return null;
         }
 
+        @Override
         @SuppressWarnings({ "rawtypes", "unchecked" })
         public Enumeration getIds()
         {
@@ -162,6 +163,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public HttpCookie access(HttpSession session,boolean secure)
     {
         long now=System.currentTimeMillis();
@@ -187,6 +189,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public void addEventListener(EventListener listener)
     {
         if (listener instanceof HttpSessionAttributeListener)
@@ -195,17 +198,22 @@
             _sessionListeners.add((HttpSessionListener)listener);
         if (listener instanceof HttpSessionIdListener)
             _sessionIdListeners.add((HttpSessionIdListener)listener);
+        addBean(listener,false);
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public void clearEventListeners()
     {
+        for (EventListener e :getBeans(EventListener.class))
+            removeBean(e);
         _sessionAttributeListeners.clear();
         _sessionListeners.clear();
         _sessionIdListeners.clear();
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public void complete(HttpSession session)
     {
         AbstractSession s = ((SessionIf)session).getSession();
@@ -237,17 +245,20 @@
                         Thread.currentThread().setContextClassLoader(serverLoader);
                         _sessionIdManager=new HashSessionIdManager();
                         server.setSessionIdManager(_sessionIdManager);
+                        server.manage(_sessionIdManager);
+                        _sessionIdManager.start();
                     }
                     finally
                     {
                         Thread.currentThread().setContextClassLoader(_loader);
                     }
                 }
+
+                // server session id is never managed by this manager
+                addBean(_sessionIdManager,false);
             }
         }
         
-        if (!_sessionIdManager.isStarted())
-            _sessionIdManager.start();
 
         // Look for a session cookie name
         if (_context!=null)
@@ -299,6 +310,7 @@
     /**
      * @return Returns the httpOnly.
      */
+    @Override
     @ManagedAttribute("true if cookies use the http only flag")
     public boolean getHttpOnly()
     {
@@ -306,6 +318,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public HttpSession getHttpSession(String nodeId)
     {
         String cluster_id = getSessionIdManager().getClusterId(nodeId);
@@ -318,18 +331,9 @@
 
     /* ------------------------------------------------------------ */
     /**
-     * @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
      */
+    @Override
     @ManagedAttribute("Session ID Manager")
     public SessionIdManager getSessionIdManager()
     {
@@ -350,16 +354,6 @@
 
     /* ------------------------------------------------------------ */
     /**
-     * @see #getSessionsMax()
-     */
-    @Deprecated
-    public int getMaxSessions()
-    {
-        return getSessionsMax();
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
      * @return maximum number of sessions
      */
     @ManagedAttribute("maximum number of simultaneous sessions")
@@ -379,33 +373,12 @@
     }
 
     /* ------------------------------------------------------------ */
-    /**
-     * @deprecated use {@link #getSessionIdManager()}
-     */
-    @Deprecated
-    public SessionIdManager getMetaManager()
-    {
-        return getSessionIdManager();
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @deprecated always returns 0. no replacement available.
-     */
-    @Deprecated
-    public int getMinSessions()
-    {
-        return 0;
-    }
-
-    /* ------------------------------------------------------------ */
     @ManagedAttribute("time before a session cookie is re-set (in s)")
     public int getRefreshCookieAge()
     {
         return _refreshCookieAge;
     }
 
-
     /* ------------------------------------------------------------ */
     /**
      * @return same as SessionCookieConfig.getSecure(). If true, session
@@ -438,8 +411,6 @@
         _secureRequestOnly = secureRequestOnly;
     }
 
-
-
     /* ------------------------------------------------------------ */
     @ManagedAttribute("the set session cookie")
     public String getSessionCookie()
@@ -473,6 +444,7 @@
      *
      * @see org.eclipse.jetty.server.SessionManager#getSessionCookie(javax.servlet.http.HttpSession, java.lang.String, boolean)
      */
+    @Override
     public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure)
     {
         if (isUsingCookies())
@@ -527,18 +499,6 @@
     }
 
     /* ------------------------------------------------------------ */
-    /**
-     * @deprecated  Need to review if it is needed.
-     */
-    @SuppressWarnings("rawtypes")
-    public Map getSessionMap()
-    {
-        throw new UnsupportedOperationException();
-    }
-
-
-
-    /* ------------------------------------------------------------ */
     @ManagedAttribute("number of currently active sessions")
     public int getSessions()
     {
@@ -546,6 +506,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     @ManagedAttribute("name of use for URL session tracking")
     public String getSessionIdPathParameterName()
     {
@@ -553,6 +514,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public String getSessionIdPathParameterNamePrefix()
     {
         return _sessionIdPathParameterNamePrefix;
@@ -562,12 +524,14 @@
     /**
      * @return Returns the usingCookies.
      */
+    @Override
     public boolean isUsingCookies()
     {
         return _usingCookies;
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public boolean isValid(HttpSession session)
     {
         AbstractSession s = ((SessionIf)session).getSession();
@@ -575,6 +539,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public String getClusterId(HttpSession session)
     {
         AbstractSession s = ((SessionIf)session).getSession();
@@ -582,6 +547,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public String getNodeId(HttpSession session)
     {
         AbstractSession s = ((SessionIf)session).getSession();
@@ -592,6 +558,7 @@
     /**
      * Create a new HttpSession for a request
      */
+    @Override
     public HttpSession newHttpSession(HttpServletRequest request)
     {
         AbstractSession session=newSession(request);
@@ -601,6 +568,7 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public void removeEventListener(EventListener listener)
     {
         if (listener instanceof HttpSessionAttributeListener)
@@ -608,17 +576,7 @@
         if (listener instanceof HttpSessionListener)
             _sessionListeners.remove(listener);
     }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @see #statsReset()
-     */
-    @Deprecated
-    public void resetStats()
-    {
-        statsReset();
-    }
-
+    
     /* ------------------------------------------------------------ */
     /**
      * Reset statistics values
@@ -643,54 +601,42 @@
     /* ------------------------------------------------------------ */
     /**
      * @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.
-     */
+    @Override
     public void setSessionIdManager(SessionIdManager metaManager)
     {
+        updateBean(_sessionIdManager, metaManager);
         _sessionIdManager=metaManager;
     }
 
-
-
     /* ------------------------------------------------------------ */
     /**
      * @param seconds
      */
+    @Override
     public void setMaxInactiveInterval(int seconds)
     {
         _dftMaxIdleSecs=seconds;
     }
 
-
     /* ------------------------------------------------------------ */
     public void setRefreshCookieAge(int ageInSeconds)
     {
         _refreshCookieAge=ageInSeconds;
     }
 
-
-
+    /* ------------------------------------------------------------ */
     public void setSessionCookie(String cookieName)
     {
         _sessionCookie=cookieName;
     }
 
-
-
     /* ------------------------------------------------------------ */
     /**
      * @param sessionHandler
      *            The sessionHandler to set.
      */
+    @Override
     public void setSessionHandler(SessionHandler sessionHandler)
     {
         _sessionHandler=sessionHandler;
@@ -698,6 +644,7 @@
 
 
     /* ------------------------------------------------------------ */
+    @Override
     public void setSessionIdPathParameterName(String param)
     {
         _sessionIdPathParameterName =(param==null||"none".equals(param))?null:param;
@@ -844,12 +791,14 @@
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
     {
         return __defaultSessionTrackingModes;
     }
 
     /* ------------------------------------------------------------ */
+    @Override
     public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
     {
         return Collections.unmodifiableSet(_sessionTrackingModes);
@@ -871,8 +820,8 @@
         return _usingURLs;
     }
 
-
     /* ------------------------------------------------------------ */
+    @Override
     public SessionCookieConfig getSessionCookieConfig()
     {
         return _cookieConfig;
@@ -917,6 +866,7 @@
     /**
      * @see org.eclipse.jetty.server.SessionManager#isCheckingRemoteSessionIdEncoding()
      */
+    @Override
     @ManagedAttribute("check remote session id encoding")
     public boolean isCheckingRemoteSessionIdEncoding()
     {
@@ -927,6 +877,7 @@
     /**
      * @see org.eclipse.jetty.server.SessionManager#setCheckingRemoteSessionIdEncoding(boolean)
      */
+    @Override
     public void setCheckingRemoteSessionIdEncoding(boolean remote)
     {
         _checkingRemoteSessionIdEncoding=remote;
@@ -1091,4 +1042,11 @@
             }
         }
     }
+
+    @Override
+    @Deprecated
+    public SessionIdManager getMetaManager()
+    {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
index beda6ce..1effd32 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
@@ -34,6 +34,7 @@
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 
+import org.eclipse.jetty.server.SessionIdManager;
 import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
 import org.eclipse.jetty.util.IO;
@@ -60,9 +61,7 @@
     final static Logger LOG = SessionHandler.LOG;
 
     protected final ConcurrentMap<String,HashedSession> _sessions=new ConcurrentHashMap<String,HashedSession>();
-    private static int __id;
     private Scheduler _timer;
-    private boolean _timerStop=false;
     private Scheduler.Task _task;
     long _scavengePeriodMs=30000;
     long _savePeriodMs=0; //don't do period saves by default
@@ -134,14 +133,11 @@
     @Override
     public void doStart() throws Exception
     {
-        super.doStart();
-
-        _timerStop=false;
         //try shared scheduler from Server first
         _timer = getSessionHandler().getServer().getBean(Scheduler.class);
         if (_timer == null)
         {
-            //try one passwed into the context
+            //try one passed into the context
             ServletContext context = ContextHandler.getCurrentContext();
             if (context!=null)
                 _timer = (Scheduler)context.getAttribute("org.eclipse.jetty.server.session.timer");   
@@ -149,12 +145,14 @@
       
         if (_timer == null)
         {
-          //make a scheduler if none useable
-            _timerStop=true;
-            _timer=new ScheduledExecutorScheduler();
-            _timer.start();
+            //make a scheduler if none useable
+            _timer=new ScheduledExecutorScheduler(toString()+"Timer",true);
+            addBean(_timer,true);
         }
-     
+        else
+            addBean(_timer,false);
+            
+        super.doStart();
 
         setScavengePeriod(getScavengePeriod());
 
@@ -186,8 +184,6 @@
             if (_task!=null)
                 _task.cancel();
             _task=null;
-            if (_timer!=null && _timerStop)
-                _timer.stop();
             _timer=null;
         }
 
@@ -427,7 +423,7 @@
     /* ------------------------------------------------------------ */
     @Override
     protected void shutdownSessions() throws Exception
-    {
+    {   
         // Invalidate all sessions to cause unbind events
         ArrayList<HashedSession> sessions=new ArrayList<HashedSession>(_sessions.values());
         int loop=100;
@@ -672,7 +668,6 @@
         if (size>0)
         {
             ClassLoadingObjectInputStream ois =  new ClassLoadingObjectInputStream(is);
-        
             for (int i=0; i<size;i++)
             {
                 String key = ois.readUTF();
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
index 451cb00..1cd77af 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
@@ -23,6 +23,7 @@
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.util.IO;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.StdErrLog;
 import org.junit.After;
@@ -41,7 +42,7 @@
     @Before
     public void quietStacks()
     {
-        enableStacks(false);
+        enableStacks(true);
     }
     
     protected void enableStacks(boolean enabled)
@@ -94,6 +95,7 @@
     public void testHashSession() throws Exception
     {
         File testDir = MavenTestingUtils.getTargetTestingDir("saved");
+        IO.delete(testDir);
         testDir.mkdirs();
         
         Server server = new Server();
@@ -109,10 +111,12 @@
         AbstractSessionIdManager idManager = new HashSessionIdManager();
         idManager.setWorkerName("foo");
         manager.setSessionIdManager(idManager);
+        server.setSessionIdManager(idManager);
         
-        idManager.start();
+        server.start();
         manager.start();
         
+        
         HashedSession session = (HashedSession)manager.newHttpSession(new Request(null, null));
         String sessionId = session.getId();
         
@@ -120,14 +124,12 @@
         session.setAttribute("two", new Integer(2));    
         
         //stop will persist sessions
-        idManager.stop();
         manager.setMaxInactiveInterval(30); //change max inactive interval for *new* sessions
         manager.stop();
         
         Assert.assertTrue("File should exist!", new File(testDir, session.getId()).exists());
         
         //start will restore sessions
-        idManager.start();
         manager.start();
         
         HashedSession restoredSession = (HashedSession)manager.getSession(sessionId);
@@ -138,5 +140,7 @@
         
         Assert.assertEquals(1, ((Integer)o).intValue());
         Assert.assertEquals(5, restoredSession.getMaxInactiveInterval());     
+        
+        server.stop();
     }
 }
diff --git a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
index e629638..9a8d616 100644
--- a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
+++ b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
@@ -21,11 +21,30 @@
 import java.io.File;
 
 import org.eclipse.jetty.server.SessionManager;
+import org.eclipse.jetty.util.IO;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 public class SessionRenewTest extends AbstractSessionRenewTest
 {
-
+    File tmpDir;
+    
+    @Before
+    public void before() throws Exception
+    {
+        tmpDir = File.createTempFile("hash-session-renew-test", null);
+        tmpDir.delete();
+        tmpDir.mkdirs();
+        tmpDir.deleteOnExit();
+    }
+    
+    @After 
+    public void after()
+    {
+        IO.delete(tmpDir);
+    }
+    
     @Override
     public AbstractTestServer createServer(int port, int max, int scavenge)
     {
@@ -37,9 +56,7 @@
             {
                 HashSessionManager sessionManager = (HashSessionManager)super.newSessionManager();
                 sessionManager.setSavePeriod(2);
-                File tmpDir = new File(System.getProperty("java.io.tmpdir"), "hash-session-renew-test");
-                tmpDir.deleteOnExit();
-                tmpDir.mkdirs();
+                
                 try
                 {
                     sessionManager.setStoreDirectory(tmpDir);