FELIX-4483 - make osgi-bundlecontext available in init methods:
- make the bundle context available to the servlet/filter's init methods
to ensure they can operate nicely in a OSGi context. Thanks to Bob P.
for providing the patch.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1587624 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
index 3413c26..126821b 100644
--- a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
+++ b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
@@ -603,6 +603,8 @@
try
{
+ context.getServletContext().setAttribute(OSGI_BUNDLE_CONTEXT, webAppBundle.getBundleContext());
+
JettyService.this.parent.addHandler(context);
context.start();
@@ -612,8 +614,6 @@
props.put(WEB_CONTEXT_PATH, deployment.getContextPath());
deployment.setRegistration(webAppBundle.getBundleContext().registerService(ServletContext.class.getName(), context.getServletContext(), props));
- context.getServletContext().setAttribute(OSGI_BUNDLE_CONTEXT, webAppBundle.getBundleContext());
-
postEvent(WebEvent.DEPLOYED(webAppBundle, extenderBundle));
}
catch (Exception e)
diff --git a/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java b/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
new file mode 100644
index 0000000..f0f23fa
--- /dev/null
+++ b/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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.felix.http.jetty.internal;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.Hashtable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.felix.http.base.internal.DispatcherServlet;
+import org.apache.felix.http.base.internal.EventDispatcher;
+import org.apache.felix.http.base.internal.HttpServiceController;
+import org.apache.felix.http.jetty.internal.JettyService.Deployment;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+
+import junit.framework.TestCase;
+import static org.mockito.Mockito.*;
+
+public class JettyServiceTest extends TestCase
+{
+
+ private static final String OSGI_BUNDLECONTEXT = "osgi-bundlecontext";
+
+ private JettyService jettyService;
+
+ private BundleContext mockBundleContext;
+
+ private DispatcherServlet dispatcherServlet;
+
+ private EventDispatcher mockEventDispatcher;
+
+ private HttpServiceController httpServiceController;
+
+ private Bundle mockBundle;
+
+ public void setUp() throws Exception
+ {
+ //Setup Mocks
+ mockBundleContext = mock(BundleContext.class);
+ mockEventDispatcher = mock(EventDispatcher.class);
+ mockBundle = mock(Bundle.class);
+
+ //Setup Behaviors
+ when(mockBundleContext.getBundle()).thenReturn(mockBundle);
+ when(mockBundle.getSymbolicName()).thenReturn("main");
+ when(mockBundle.getVersion()).thenReturn(new Version("1.0.0"));
+ when(mockBundle.getHeaders()).thenReturn(new Hashtable<String, String>());
+
+ httpServiceController = new HttpServiceController(mockBundleContext);
+ dispatcherServlet = new DispatcherServlet(httpServiceController);
+ jettyService = new JettyService(mockBundleContext, dispatcherServlet, mockEventDispatcher, httpServiceController);
+
+ jettyService.start();
+ }
+
+ /**
+ *
+ * Tests to ensure the osgi-bundlecontext is available for init methods.
+ *
+ * @throws MalformedURLException
+ * @throws InterruptedException
+ */
+ public void testInitBundleContextDeployIT() throws MalformedURLException, InterruptedException
+ {
+ //Setup mocks
+ Deployment mockDeployment = mock(Deployment.class);
+ Bundle mockBundle = mock(Bundle.class);
+ BundleContext mockBundleContext = mock(BundleContext.class);
+
+ //Setup behaviors
+ when(mockDeployment.getBundle()).thenReturn(mockBundle);
+ when(mockBundle.getBundleContext()).thenReturn(mockBundleContext);
+ when(mockBundle.getSymbolicName()).thenReturn("test");
+ when(mockBundle.getVersion()).thenReturn(new Version("0.0.1"));
+
+ Dictionary<String, String> headerProperties = new Hashtable<String, String>();
+ headerProperties.put("Web-ContextPath", "test");
+ when(mockBundle.getHeaders()).thenReturn(headerProperties);
+ when(mockDeployment.getContextPath()).thenReturn("test");
+ when(mockBundle.getEntry("/")).thenReturn(new URL("http://www.apache.com"));
+ when(mockBundle.getState()).thenReturn(Bundle.ACTIVE);
+
+ EnumSet<DispatcherType> dispatcherSet = EnumSet.allOf(DispatcherType.class);
+ dispatcherSet.add(DispatcherType.REQUEST);
+
+ WebAppBundleContext webAppBundleContext = new WebAppBundleContext("/", mockBundle, this.getClass().getClassLoader());
+
+ final CountDownLatch testLatch = new CountDownLatch(2);
+
+ //Add a Filter to test whether the osgi-bundlecontext is available at init
+ webAppBundleContext.addServlet(new ServletHolder(new Servlet()
+ {
+ public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException
+ {
+ // Do Nothing
+ }
+
+ public void init(ServletConfig config) throws ServletException
+ {
+ ServletContext context = config.getServletContext();
+
+ assertNotNull(context.getAttribute(OSGI_BUNDLECONTEXT));
+
+ testLatch.countDown();
+ }
+
+ public String getServletInfo()
+ {
+ return null;
+ }
+
+ public ServletConfig getServletConfig()
+ {
+ return null;
+ }
+
+ public void destroy()
+ {
+ // Do Nothing
+ }
+ }), "/test1");
+
+ webAppBundleContext.addFilter(new FilterHolder(new Filter()
+ {
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+ ServletContext context = filterConfig.getServletContext();
+
+ assertNotNull(context.getAttribute(OSGI_BUNDLECONTEXT));
+
+ testLatch.countDown();
+ }
+
+ public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain) throws IOException, ServletException
+ {
+ // Do Nothing
+ }
+
+ public void destroy()
+ {
+ // Do Nothing
+
+ }
+ }), "/test2", dispatcherSet);
+
+ jettyService.deploy(mockDeployment, webAppBundleContext);
+
+ //Pause since service is multi-threaded.
+ //Fail if takes too long.
+ if (!testLatch.await(6, TimeUnit.SECONDS))
+ {
+ fail("Test Was not asserted");
+ }
+ }
+}
\ No newline at end of file