Forráskód Böngészése

SEC-268: allow for delayed obtaining of app context reference

Luke Taylor 19 éve
szülő
commit
46cc1bec1e

+ 30 - 29
core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java

@@ -21,25 +21,27 @@ import org.apache.commons.logging.LogFactory;
 import org.springframework.context.ApplicationContext;
 
 import org.springframework.web.context.support.WebApplicationContextUtils;
-import org.springframework.util.Assert;
 
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSessionEvent;
 import javax.servlet.http.HttpSessionListener;
 
 
 /**
  * Declared in web.xml as <br>
- * <code> &lt;listener&gt;<br>
- * &lt;listener-class&gt;org.acegisecurity.ui.session.HttpSessionEventPublisher&lt;/listener-class&gt;<br>
- * &lt;/listener&gt;<br>
- * </code> Publishes <code>HttpSessionApplicationEvent</code>s to the Spring
- * Root WebApplicationContext. <br>
+ * <pre>
+ * &lt;listener&gt;
+ * &lt;listener-class&gt;org.acegisecurity.ui.session.HttpSessionEventPublisher&lt;/listener-class&gt;
+ * &lt;/listener&gt;
+ * </pre>
+ * Publishes <code>HttpSessionApplicationEvent</code>s to the Spring
+ * Root WebApplicationContext.
  * Maps javax.servlet.http.HttpSessionListener.sessionCreated() to {@link
- * HttpSessionCreatedEvent}. <br>
+ * HttpSessionCreatedEvent}.
  * Maps javax.servlet.http.HttpSessionListener.sessionDestroyed() to {@link
- * HttpSessionDestroyedEvent}. <br>
+ * HttpSessionDestroyedEvent}.
  *
  * @author Ray Krueger
  */
@@ -51,7 +53,8 @@ public class HttpSessionEventPublisher implements HttpSessionListener,
 
     //~ Instance fields ========================================================
 
-    private ApplicationContext context;
+    private ApplicationContext appContext;
+    private ServletContext servletContext = null;
 
     //~ Methods ================================================================
 
@@ -64,22 +67,28 @@ public class HttpSessionEventPublisher implements HttpSessionListener,
 
     /**
      * Handled internally by a call to {@link
-     * org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext(javax.servlet.ServletContext)}
+     * org.springframework.web.appContext.support.WebApplicationContextUtils#getRequiredWebApplicationContext(javax.servlet.ServletContext)}
      *
      * @param event the ServletContextEvent passed in by the container,
      *        event.getServletContext() will be used to get the
      *        WebApplicationContext
      */
     public void contextInitialized(ServletContextEvent event) {
-        if (log.isDebugEnabled())
-            log.debug("Received ServletContextEvent: " + event);
-        setContext(WebApplicationContextUtils.getRequiredWebApplicationContext(
-                event.getServletContext()));
+        log.debug("Received ServletContextEvent: " + event);
+
+        appContext = WebApplicationContextUtils.getWebApplicationContext(
+                event.getServletContext());
+
+        if(appContext == null) {
+            log.warn("Web application context is null. Will delay initialization until it's first used.");
+            servletContext = event.getServletContext();
+        }
+
     }
 
     /**
      * Handles the HttpSessionEvent by publishing a {@link
-     * HttpSessionCreatedEvent} to the application context.
+     * HttpSessionCreatedEvent} to the application appContext.
      *
      * @param event HttpSessionEvent passed in by the container
      */
@@ -94,7 +103,7 @@ public class HttpSessionEventPublisher implements HttpSessionListener,
 
     /**
      * Handles the HttpSessionEvent by publishing a {@link
-     * HttpSessionDestroyedEvent} to the application context.
+     * HttpSessionDestroyedEvent} to the application appContext.
      *
      * @param event The HttpSessionEvent pass in by the container
      */
@@ -107,19 +116,11 @@ public class HttpSessionEventPublisher implements HttpSessionListener,
         getContext().publishEvent(e);
     }
 
-    /**
-     * Package level method for testing and internal usage
-     *
-     * @param context The ApplicationContext this class will use to publish
-     *        events
-     */
-    void setContext(ApplicationContext context) {
-        this.context = context;
-        log.debug("Using context: " + context);
-    }
-
     ApplicationContext getContext() {
-       Assert.notNull(context, "setContext(...) never called, ApplicationContext must not be null");
-        return context;
+        if(appContext == null) {
+            appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
+        }
+
+        return appContext;
     }
 }

+ 20 - 16
core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java

@@ -20,13 +20,10 @@ import junit.framework.TestCase;
 import org.springframework.mock.web.MockServletContext;
 import org.springframework.mock.web.MockHttpSession;
 import org.springframework.web.context.support.StaticWebApplicationContext;
-import org.springframework.context.ConfigurableApplicationContext;
 
 import javax.servlet.ServletContextEvent;
 import javax.servlet.http.HttpSessionEvent;
 
-import org.acegisecurity.MockApplicationContext;
-
 
 /**
  * The HttpSessionEventPublisher tests
@@ -39,9 +36,8 @@ public class HttpSessionEventPublisherTests extends TestCase {
 
     /**
      * It's not that complicated so we'll just run it straight through here.
-     * @throws Exception
      */
-    public void testPublisher() throws Exception {
+    public void testPublisher() {
         HttpSessionEventPublisher publisher = new HttpSessionEventPublisher();
 
         StaticWebApplicationContext context = new StaticWebApplicationContext();
@@ -77,21 +73,29 @@ public class HttpSessionEventPublisherTests extends TestCase {
         publisher.contextDestroyed(new ServletContextEvent(servletContext));
     }
 
-    public void testContext() throws Exception {
-        HttpSessionEventPublisher pub  = new HttpSessionEventPublisher();
-        ConfigurableApplicationContext c = MockApplicationContext.getContext();
-        pub.setContext(c);
-        assertEquals(c, pub.getContext());
+
+    public void testDelayedContextInitializationSucceeds() {
+        HttpSessionEventPublisher publisher = new HttpSessionEventPublisher();
+        MockServletContext servletContext = new MockServletContext();
+
+        // shouldn't fail, even with null context
+        publisher.contextInitialized(new ServletContextEvent(servletContext));
+
+
+        StaticWebApplicationContext context = new StaticWebApplicationContext();
+        context.setServletContext(servletContext);
+
+
     }
 
-    public void testNullContextCheck() throws Exception {
-        HttpSessionEventPublisher pub  = new HttpSessionEventPublisher();
+    public void testGetContextThrowsExceptionIfContextNotSet() {
+        HttpSessionEventPublisher publisher  = new HttpSessionEventPublisher();
+        publisher.contextInitialized(new ServletContextEvent(new MockServletContext()));
 
         try {
-            pub.getContext();
-            fail("IllegalArgumentException expected, the context is null");
-        } catch (IllegalArgumentException e) {
-            assertTrue(true);
+            publisher.getContext();
+            fail("IllegalStateException expected when no context set");
+        } catch (IllegalStateException expected) {
         }
     }
 }