Add StoraeService implementaiton that produces events when objects are add or created.
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 2 Sep 2008 11:08:43 +0000 (11:08 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 2 Sep 2008 11:08:43 +0000 (11:08 +0000)
Fix SIDP-206

git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/branches/REL_2@2757 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

doc/README.txt
doc/RELEASE_NOTES.txt
src/installer/resources/conf-tmpl/internal.xml
src/main/java/edu/internet2/middleware/shibboleth/idp/authn/AuthenticationEngine.java
src/main/java/edu/internet2/middleware/shibboleth/idp/session/impl/SessionManagerImpl.java

index 44e481d..10103ae 100644 (file)
@@ -26,6 +26,11 @@ Upgrading
 from 2.0.0 to 2.1.0
 -------------------
 The following configuration changes must be made to upgrade from 2.0.0 to 2.1.0
+- in servie.xml replace 'org.opensaml.util.storage.MapBasedStorageService' with 
+  'edu.internet2.middleware.shibboleth.common.util.EventingMapBasedStorageService'
+  as the value for the class attribute of bean 'shibboleth.StorageService' (line 82 in the
+  default configuration file)
+  
 - in service.xml add the service 'shibboleth.StorageService' to the whitespace delimited 
   list of services already present in the service, shibboleth.ServiceServletContextAttributeExporter
   (service definition starts at line 57 in the default configuration file)
index 9f8e304..3906793 100644 (file)
@@ -20,6 +20,7 @@ Changes in Release 2.1.0
 [SIDP-199] - loss of login context when deploying the IdP to tomcat's ROOT context
 [SIDP-201] - IdP sends SAML 1 authentication responses without audience conditions
 [SIDP-203] - Insufficient information logged to track down errant users
+[SIDP-206] - SessionManagerEntry's back reference to the SessionManager object interferes with clustering
 [SIDP-209] - Enforce SAML 2 metadata SPSSODescriptor/@AuthnRequestsSigned
 [SIDP-214] - Installer needs to put (at least) bcprov onto the calsspath before it runs ant
 [SIDP-222] - Template engine used by LDAP and database connectors throw an NPE on startup
\ No newline at end of file
index 1381824..3785b88 100644 (file)
@@ -79,7 +79,7 @@
         </property>
     </bean>
 
-    <bean id="shibboleth.StorageService" class="org.opensaml.util.storage.MapBasedStorageService" depends-on="shibboleth.LogbackLogging" />
+    <bean id="shibboleth.StorageService" class="edu.internet2.middleware.shibboleth.common.util.EventingMapBasedStorageService" depends-on="shibboleth.LogbackLogging" />
 
     <bean id="shibboleth.StorageServiceSweeper" class="org.opensaml.util.storage.ExpiringObjectStorageServiceSweeper" depends-on="shibboleth.LogbackLogging">
         <constructor-arg ref="shibboleth.TaskTimer" />
index 6c944ba..43f9e84 100644 (file)
@@ -71,6 +71,7 @@ public class AuthenticationEngine extends HttpServlet {
     public static final String LOGIN_CONTEXT_KEY_NAME = "_idp_authn_lc_key";
 
     /** Serial version UID. */
+    private static final long serialVersionUID = -8479060989001890156L;
 
     /** Class logger. */
     private static final Logger LOG = LoggerFactory.getLogger(AuthenticationEngine.class);
index 5982a79..b707cbb 100644 (file)
@@ -25,17 +25,26 @@ import org.joda.time.DateTime;
 import org.opensaml.util.storage.ExpiringObject;
 import org.opensaml.util.storage.StorageService;
 import org.opensaml.xml.util.DatatypeHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
 
 import edu.internet2.middleware.shibboleth.common.session.LoginEvent;
 import edu.internet2.middleware.shibboleth.common.session.LogoutEvent;
 import edu.internet2.middleware.shibboleth.common.session.SessionManager;
+import edu.internet2.middleware.shibboleth.common.util.EventingMapBasedStorageService.AddEntryEvent;
+import edu.internet2.middleware.shibboleth.common.util.EventingMapBasedStorageService.RemoveEntryEvent;
 import edu.internet2.middleware.shibboleth.idp.session.Session;
 
 /** Manager of IdP sessions. */
-public class SessionManagerImpl implements SessionManager<Session>, ApplicationContextAware {
+public class SessionManagerImpl implements SessionManager<Session>, ApplicationContextAware, ApplicationListener {
+
+    /** Class logger. */
+    private final Logger log = LoggerFactory.getLogger(SessionManagerImpl.class);
 
     /** Spring context used to publish login and logout events. */
     private ApplicationContext appCtx;
@@ -93,11 +102,11 @@ public class SessionManagerImpl implements SessionManager<Session>, ApplicationC
         String sessionID = Hex.encode(sid);
 
         Session session = new SessionImpl(sessionID, sessionLifetime);
-        SessionManagerEntry sessionEntry = new SessionManagerEntry(this, session, sessionLifetime);
+        SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
         sessionStore.put(partition, sessionID, sessionEntry);
 
         MDC.put("idpSessionId", sessionID);
-
+        log.trace("Created session {}", sessionID);
         appCtx.publishEvent(new LoginEvent(session));
         return session;
     }
@@ -112,9 +121,9 @@ public class SessionManagerImpl implements SessionManager<Session>, ApplicationC
         MDC.put("idpSessionId", sessionID);
 
         Session session = new SessionImpl(sessionID, sessionLifetime);
-        SessionManagerEntry sessionEntry = new SessionManagerEntry(this, session, sessionLifetime);
+        SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
         sessionStore.put(partition, sessionID, sessionEntry);
-        appCtx.publishEvent(new LoginEvent(session));
+        log.trace("Created session {}", sessionID);
         return session;
     }
 
@@ -124,10 +133,7 @@ public class SessionManagerImpl implements SessionManager<Session>, ApplicationC
             return;
         }
 
-        SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
-        if (sessionEntry != null) {
-            appCtx.publishEvent(new LogoutEvent(sessionEntry.getSession()));
-        }
+        sessionStore.remove(partition, sessionID);
     }
 
     /** {@inheritDoc} */
@@ -166,25 +172,51 @@ public class SessionManagerImpl implements SessionManager<Session>, ApplicationC
 
         sessionEntry.getSessionIndexes().add(index);
         sessionStore.put(partition, index, sessionEntry);
+        log.trace("Added index {} to session {}", index, session.getSessionID());
         return true;
     }
 
     /** {@inheritDoc} */
+    public void onApplicationEvent(ApplicationEvent event) {
+        log.trace("Received event {}", event.getClass().getName());
+        if(event instanceof AddEntryEvent){
+            AddEntryEvent addEvent = (AddEntryEvent)event;
+            if(addEvent.getValue() instanceof SessionManagerEntry){
+                SessionManagerEntry sessionEntry = (SessionManagerEntry) addEvent.getValue();
+                appCtx.publishEvent(new LoginEvent(sessionEntry.getSession()));
+            }
+        }
+        
+        if (event instanceof RemoveEntryEvent) {
+            RemoveEntryEvent removeEvent = (RemoveEntryEvent) event;
+            if (removeEvent.getValue() instanceof SessionManagerEntry) {
+                SessionManagerEntry sessionEntry = (SessionManagerEntry) removeEvent.getValue();
+                log.trace("Destroyed session {} for principal {}", sessionEntry.getSessionId(), sessionEntry
+                        .getSession().getPrincipalName());
+                appCtx.publishEvent(new LogoutEvent(sessionEntry.getSession()));
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
     public void removeSessionIndex(String index) {
         SessionManagerEntry sessionEntry = sessionStore.remove(partition, index);
         if (sessionEntry != null) {
+            log.trace("Removing index {} for session {}", index, sessionEntry.getSessionId());
             sessionEntry.getSessionIndexes().remove(index);
         }
     }
 
     /** {@inheritDoc} */
     public void setApplicationContext(ApplicationContext applicationContext) {
-        appCtx = applicationContext;
+        ApplicationContext rootContext = applicationContext;
+        while(rootContext.getParent() != null){
+            rootContext = rootContext.getParent();
+        }
+        appCtx = rootContext;
     }
 
-    /**
-     * Session store entry.
-     */
+    /** Session store entry. */
     public class SessionManagerEntry implements ExpiringObject {
 
         /** User's session. */
@@ -193,21 +225,16 @@ public class SessionManagerImpl implements SessionManager<Session>, ApplicationC
         /** Indexes for this session. */
         private List<String> indexes;
 
-        /** Manager that owns the session. */
-        private SessionManager<Session> sessionManager;
-
         /** Time this entry expires. */
         private DateTime expirationTime;
 
         /**
          * Constructor.
          * 
-         * @param manager manager that owns the session
          * @param session user session
          * @param lifetime lifetime of session
          */
-        public SessionManagerEntry(SessionManager<Session> manager, Session session, long lifetime) {
-            sessionManager = manager;
+        public SessionManagerEntry(Session session, long lifetime) {
             userSession = session;
             expirationTime = new DateTime().plus(lifetime);
             indexes = new Vector<String>();
@@ -253,7 +280,7 @@ public class SessionManagerImpl implements SessionManager<Session>, ApplicationC
 
         /** {@inheritDoc} */
         public void onExpire() {
-            sessionManager.destroySession(userSession.getSessionID());
+
         }
     }
 }
\ No newline at end of file