DELTESPIKE-377 Added support for injecting ServletContext

Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/9fc325a6
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/9fc325a6
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/9fc325a6

Branch: refs/heads/master
Commit: 9fc325a6422fb0e24ea29af40b18afa4a4affcd1
Parents: d49cc27
Author: Christian Kaltepoth <[email protected]>
Authored: Tue Jun 4 17:27:46 2013 +0200
Committer: Christian Kaltepoth <[email protected]>
Committed: Thu Jun 13 06:53:29 2013 +0200

----------------------------------------------------------------------
 .../servlet/impl/ServletContextHolder.java      | 105 +++++++++++++++++++
 .../impl/ServletEventBridgeListener.java        |  10 +-
 .../servlet/impl/ServletObjectProducer.java     |   9 ++
 .../producer/ServletContextInjectionTest.java   |  78 ++++++++++++++
 4 files changed, 201 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/9fc325a6/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletContextHolder.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletContextHolder.java
 
b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletContextHolder.java
new file mode 100644
index 0000000..e590cc7
--- /dev/null
+++ 
b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletContextHolder.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.servlet.impl;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletContext;
+
+/**
+ * This class holds the {@link ServletContext} for each context class loader.
+ * 
+ * @author Christian Kaltepoth
+ */
+class ServletContextHolder
+{
+
+    private static final Logger log = 
Logger.getLogger(ServletContextHolder.class.getName());
+
+    private static final Map<ClassLoader, ServletContext> 
CONTEXT_BY_CLASSLOADER = Collections.synchronizedMap(
+            new WeakHashMap<ClassLoader, ServletContext>());
+
+    private ServletContextHolder()
+    {
+        // hide constructor
+    }
+
+    /**
+     * Bind the supplied {@link ServletContext} to the current context class 
loader. Subsequent calls to {@link #get()}
+     * with the same context class loader will always return this context.
+     * 
+     * @param servletContext
+     *            The context to bind to the context class loader
+     */
+    static void bind(ServletContext servletContext)
+    {
+        ClassLoader classLoader = getContextClassLoader();
+        ServletContext existingContext = 
CONTEXT_BY_CLASSLOADER.put(classLoader, servletContext);
+        if (existingContext != null)
+        {
+            throw new IllegalArgumentException("There is already a 
ServletContext associated with class loader: "
+                    + classLoader);
+        }
+    }
+
+    /**
+     * Returns the {@link ServletContext} associated with the current context 
class loader.
+     * 
+     * @throws IllegalStateException
+     *             if there is no {@link ServletContext} stored for the 
current context class loader
+     */
+    static ServletContext get()
+    {
+        ClassLoader classLoader = getContextClassLoader();
+        ServletContext servletContext = 
CONTEXT_BY_CLASSLOADER.get(classLoader);
+        if (servletContext == null)
+        {
+            throw new IllegalStateException("There is no ServletContext stored 
for class loader: " + classLoader);
+        }
+        return servletContext;
+    }
+
+    /**
+     * Releases the {@link ServletContext} from the current context class 
loader. Subsequent calls to {@link #get()}
+     * with the same context class loader will return <code>null</code>.
+     */
+    static void release()
+    {
+        ClassLoader classLoader = getContextClassLoader();
+        ServletContext removedContext = 
CONTEXT_BY_CLASSLOADER.remove(classLoader);
+        if (removedContext == null)
+        {
+            log.warning("Cannot find a ServletContext to release for class 
loader: " + classLoader);
+        }
+    }
+
+    private static ClassLoader getContextClassLoader()
+    {
+        ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+        if (classLoader == null)
+        {
+            throw new IllegalStateException("Unable to obtain the context 
class loader for the current thread");
+        }
+        return classLoader;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/9fc325a6/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
 
b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
index a339c5c..21f7450 100644
--- 
a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
+++ 
b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
@@ -38,13 +38,21 @@ public class ServletEventBridgeListener extends 
EventEmitter implements ServletC
     @Override
     public void contextInitialized(ServletContextEvent sce)
     {
+        ServletContextHolder.bind(sce.getServletContext());
         fireEvent(sce.getServletContext(), WebLiteral.INSTANCE, 
InitializedLiteral.INSTANCE);
     }
 
     @Override
     public void contextDestroyed(ServletContextEvent sce)
     {
-        fireEvent(sce.getServletContext(), WebLiteral.INSTANCE, 
DestroyedLiteral.INSTANCE);
+        try
+        {
+            fireEvent(sce.getServletContext(), WebLiteral.INSTANCE, 
DestroyedLiteral.INSTANCE);
+        }
+        finally
+        {
+            ServletContextHolder.release();
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/9fc325a6/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletObjectProducer.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletObjectProducer.java
 
b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletObjectProducer.java
index 7421c49..07d1798 100644
--- 
a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletObjectProducer.java
+++ 
b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletObjectProducer.java
@@ -24,6 +24,7 @@ import javax.enterprise.context.RequestScoped;
 import javax.enterprise.context.SessionScoped;
 import javax.enterprise.inject.Produces;
 import javax.enterprise.inject.Typed;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
@@ -37,6 +38,7 @@ import org.apache.deltaspike.servlet.api.Web;
  * following objects are supported:
  * 
  * <ul>
+ * <li>{@link ServletContext}</li>
  * <li>{@link ServletRequest}</li>
  * <li>{@link HttpServletRequest}</li>
  * <li>{@link ServletResponse}</li>
@@ -52,6 +54,13 @@ public class ServletObjectProducer
 
     @Produces
     @Web
+    public ServletContext getServletContext()
+    {
+        return ServletContextHolder.get();
+    }
+
+    @Produces
+    @Web
     @RequestScoped
     public ServletRequest getServletRequest()
     {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/9fc325a6/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/ServletContextInjectionTest.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/ServletContextInjectionTest.java
 
b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/ServletContextInjectionTest.java
new file mode 100644
index 0000000..781867b
--- /dev/null
+++ 
b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/ServletContextInjectionTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.test.servlet.impl.producer;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+
+import org.apache.deltaspike.servlet.api.Web;
+import org.apache.deltaspike.test.category.WebProfileCategory;
+import org.apache.deltaspike.test.servlet.impl.Deployments;
+import org.hamcrest.Matchers;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptors;
+import org.jboss.shrinkwrap.descriptor.api.spec.servlet.web.WebAppDescriptor;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+/**
+ * Test which validates that the {@link ServletContext} can be injected.
+ * 
+ * @author Christian Kaltepoth
+ */
+@RunWith(Arquillian.class)
+@Category(WebProfileCategory.class)
+public class ServletContextInjectionTest
+{
+
+    @Deployment
+    public static WebArchive getDeployment()
+    {
+        return ShrinkWrap.create(WebArchive.class, "test.war")
+                .addAsLibraries(Deployments.getDeltaSpikeCoreArchives())
+                .addAsLibraries(Deployments.getDeltaSpikeServletArchives())
+                .addAsLibraries(Deployments.getTestSupportArchives())
+                .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml")
+                .setWebXML(new StringAsset(
+                        Descriptors.create(WebAppDescriptor.class)
+                                .displayName("ServletContextInjection")
+                                .exportAsString()));
+
+    }
+
+    @Inject
+    @Web
+    private ServletContext servletContext;
+
+    @Test
+    public void shouldInjectServletContext() throws Exception
+    {
+        assertNotNull("ServletContext was not injected", servletContext);
+        assertThat(servletContext.getServletContextName(), 
Matchers.is("ServletContextInjection"));
+    }
+
+}

Reply via email to