diff --git a/core/src/main/java/org/acegisecurity/ui/session/HttpSessionApplicationEvent.java b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionApplicationEvent.java new file mode 100644 index 0000000000..fbf860658b --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionApplicationEvent.java @@ -0,0 +1,50 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.session; + +import org.springframework.context.ApplicationEvent; + +import javax.servlet.http.HttpSession; + + +/** + * Parent class for published HttpSession events + * + * @author Ray Krueger + */ +public abstract class HttpSessionApplicationEvent extends ApplicationEvent { + //~ Constructors =========================================================== + + /** + * Base constructor for all subclasses must have an HttpSession + * + * @param httpSession The session to carry as the event source. + */ + public HttpSessionApplicationEvent(HttpSession httpSession) { + super(httpSession); + } + + //~ Methods ================================================================ + + /** + * Get the HttpSession that is the cause of the event + * + * @return HttpSession instance + */ + public HttpSession getSession() { + return (HttpSession) getSource(); + } +} diff --git a/core/src/main/java/org/acegisecurity/ui/session/HttpSessionCreatedEvent.java b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionCreatedEvent.java new file mode 100644 index 0000000000..cf61f59d16 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionCreatedEvent.java @@ -0,0 +1,33 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.session; + +import javax.servlet.http.HttpSession; + + +/** + * Published by the {@link HttpSessionEventPublisher} when a HttpSession is + * destroyed by the container + * + * @author Ray Krueger + */ +public class HttpSessionCreatedEvent extends HttpSessionApplicationEvent { + //~ Constructors =========================================================== + + public HttpSessionCreatedEvent(HttpSession o) { + super(o); + } +} diff --git a/core/src/main/java/org/acegisecurity/ui/session/HttpSessionDestroyedEvent.java b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionDestroyedEvent.java new file mode 100644 index 0000000000..9b26fe2fc4 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionDestroyedEvent.java @@ -0,0 +1,33 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.session; + +import javax.servlet.http.HttpSession; + + +/** + * Published by the {@link HttpSessionEventPublisher} when a HttpSession is + * created in the container + * + * @author Ray Krueger + */ +public class HttpSessionDestroyedEvent extends HttpSessionApplicationEvent { + //~ Constructors =========================================================== + + public HttpSessionDestroyedEvent(HttpSession o) { + super(o); + } +} diff --git a/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java new file mode 100644 index 0000000000..53583530b0 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java @@ -0,0 +1,117 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.context.ApplicationContext; + +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + + +/** + * Declared in web.xml as
+ * <listener>
+ * <listener-class>net.sf.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
+ * </listener>
+ *
Publishes HttpSessionApplicationEvents to the Spring + * Root WebApplicationContext.
+ * Maps javax.servlet.http.HttpSessionListener.sessionCreated() to {@link + * HttpSessionCreatedEvent}.
+ * Maps javax.servlet.http.HttpSessionListener.sessionDestroyed() to {@link + * HttpSessionDestroyedEvent}.
+ * + * @author Ray Krueger + */ +public class HttpSessionEventPublisher implements HttpSessionListener, + ServletContextListener { + //~ Static fields/initializers ============================================= + + private static final Log log = LogFactory.getLog(HttpSessionEventPublisher.class); + + //~ Instance fields ======================================================== + + private ApplicationContext context; + + //~ Methods ================================================================ + + /** + * Not implemented + * + * @param event + */ + public void contextDestroyed(ServletContextEvent event) {} + + /** + * Handled internally by a call to {@link + * org.springframework.web.context.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) { + setContext(WebApplicationContextUtils.getRequiredWebApplicationContext( + event.getServletContext())); + } + + /** + * Handles the HttpSessionEvent by publishing a {@link + * HttpSessionCreatedEvent} to the application context. + * + * @param event HttpSessionEvent passed in by the container + */ + public void sessionCreated(HttpSessionEvent event) { + HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event + .getSession()); + + log.debug("Publishing event: " + e); + + context.publishEvent(e); + } + + /** + * Handles the HttpSessionEvent by publishing a {@link + * HttpSessionDestroyedEvent} to the application context. + * + * @param event The HttpSessionEvent pass in by the container + */ + public void sessionDestroyed(HttpSessionEvent event) { + HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event + .getSession()); + + log.debug("Publishing event: " + e); + + context.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); + } +} diff --git a/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java b/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java new file mode 100644 index 0000000000..5efdcaaaaa --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java @@ -0,0 +1,77 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.session; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.MockHttpSession; + +import org.springframework.mock.web.MockServletContext; + +import org.springframework.web.context.support.StaticWebApplicationContext; + +import javax.servlet.ServletContextEvent; +import javax.servlet.http.HttpSessionEvent; + + +/** + * The HttpSessionEventPublisher tests + * + * @author Ray Krueger + */ +public class HttpSessionEventPublisherTests extends TestCase { + //~ Methods ================================================================ + + /** + * It's not that complicated so we'll just run it straight through here. + * @throws Exception + */ + public void testPublisher() throws Exception { + HttpSessionEventPublisher publisher = new HttpSessionEventPublisher(); + + StaticWebApplicationContext context = new StaticWebApplicationContext(); + + MockServletContext servletContext = new MockServletContext(); + servletContext.setAttribute(StaticWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, + context); + + context.setServletContext(servletContext); + context.registerSingleton("listener", TestListener.class, null); + context.refresh(); + + publisher.contextInitialized(new ServletContextEvent(servletContext)); + + MockHttpSession session = new MockHttpSession(); + TestListener listener = (TestListener) context.getBean("listener"); + + HttpSessionEvent event = new HttpSessionEvent(session); + publisher.sessionCreated(event); + + assertNotNull(listener.getCreatedEvent()); + assertNull(listener.getDestroyedEvent()); + assertEquals(session, listener.getCreatedEvent().getSession()); + + listener.setCreatedEvent(null); + listener.setDestroyedEvent(null); + + publisher.sessionDestroyed(event); + assertNotNull(listener.getDestroyedEvent()); + assertNull(listener.getCreatedEvent()); + assertEquals(session, listener.getDestroyedEvent().getSession()); + + publisher.contextDestroyed(new ServletContextEvent(servletContext)); + } +} diff --git a/core/src/test/java/org/acegisecurity/ui/session/TestListener.java b/core/src/test/java/org/acegisecurity/ui/session/TestListener.java new file mode 100644 index 0000000000..bc02b3367a --- /dev/null +++ b/core/src/test/java/org/acegisecurity/ui/session/TestListener.java @@ -0,0 +1,58 @@ +/* Copyright 2004, 2005 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.ui.session; + +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; + + +/** + * Listener for tests + * + * @author Ray Krueger + */ +public class TestListener implements ApplicationListener { + //~ Instance fields ======================================================== + + private HttpSessionCreatedEvent createdEvent; + private HttpSessionDestroyedEvent destroyedEvent; + + //~ Methods ================================================================ + + public void setCreatedEvent(HttpSessionCreatedEvent createdEvent) { + this.createdEvent = createdEvent; + } + + public HttpSessionCreatedEvent getCreatedEvent() { + return createdEvent; + } + + public void setDestroyedEvent(HttpSessionDestroyedEvent destroyedEvent) { + this.destroyedEvent = destroyedEvent; + } + + public HttpSessionDestroyedEvent getDestroyedEvent() { + return destroyedEvent; + } + + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof HttpSessionCreatedEvent) { + createdEvent = (HttpSessionCreatedEvent) event; + } else if (event instanceof HttpSessionDestroyedEvent) { + destroyedEvent = (HttpSessionDestroyedEvent) event; + } + } +} diff --git a/samples/contacts/src/main/webapp/filter/WEB-INF/web.xml b/samples/contacts/src/main/webapp/filter/WEB-INF/web.xml index dc056eb81c..e713b052b8 100644 --- a/samples/contacts/src/main/webapp/filter/WEB-INF/web.xml +++ b/samples/contacts/src/main/webapp/filter/WEB-INF/web.xml @@ -57,7 +57,11 @@ org.springframework.web.util.Log4jConfigListener - + + + net.sf.acegisecurity.ui.session.HttpSessionEventPublisher + +