FELIX-4940 : Use servlet 3.0 API to register all required web components
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1687617 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/proxy/pom.xml b/http/proxy/pom.xml
index 7479681..482e9dd 100644
--- a/http/proxy/pom.xml
+++ b/http/proxy/pom.xml
@@ -62,6 +62,7 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
+ <version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
diff --git a/http/proxy/src/main/java/org/apache/felix/http/proxy/DispatcherTracker.java b/http/proxy/src/main/java/org/apache/felix/http/proxy/DispatcherTracker.java
index 9901575..82ddba3 100644
--- a/http/proxy/src/main/java/org/apache/felix/http/proxy/DispatcherTracker.java
+++ b/http/proxy/src/main/java/org/apache/felix/http/proxy/DispatcherTracker.java
@@ -16,14 +16,19 @@
*/
package org.apache.felix.http.proxy;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Filter;
-import org.osgi.framework.Constants;
-import javax.servlet.http.HttpServlet;
import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServlet;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * @deprecated
+ */
+@Deprecated
public final class DispatcherTracker
extends ServiceTracker
{
diff --git a/http/proxy/src/main/java/org/apache/felix/http/proxy/ProxyListener.java b/http/proxy/src/main/java/org/apache/felix/http/proxy/ProxyListener.java
index 175b5f2..1a0923b 100644
--- a/http/proxy/src/main/java/org/apache/felix/http/proxy/ProxyListener.java
+++ b/http/proxy/src/main/java/org/apache/felix/http/proxy/ProxyListener.java
@@ -18,8 +18,6 @@
*/
package org.apache.felix.http.proxy;
-import java.util.EventListener;
-
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
@@ -29,12 +27,10 @@
import javax.servlet.http.HttpSessionIdListener;
import javax.servlet.http.HttpSessionListener;
+import org.apache.felix.http.proxy.impl.EventDispatcherTracker;
+import org.apache.felix.http.proxy.impl.ProxyServletContextListener;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
/**
* The <code>ProxyListener</code> implements a Servlet API listener for HTTP
@@ -42,7 +38,9 @@
* and forwarded to the event dispatcher.
*
* @since 2.1.0
+ * @deprecated Use the {@link ProxyServletContextListener} instead.
*/
+@Deprecated
public class ProxyListener
implements HttpSessionAttributeListener,
HttpSessionListener,
@@ -50,15 +48,9 @@
ServletContextListener
{
- private ServletContext servletContext;
+ private volatile ServletContext servletContext;
- private ServiceTracker eventDispatcherTracker;
-
- private HttpSessionListener sessionDispatcher;
-
- private HttpSessionIdListener sessionIdDispatcher;
-
- private HttpSessionAttributeListener attributeDispatcher;
+ private volatile EventDispatcherTracker eventDispatcherTracker;
// ---------- ServletContextListener
@@ -162,18 +154,7 @@
try
{
BundleContext bundleContext = (BundleContext) bundleContextAttr;
- Filter filter = createFilter(bundleContext, null);
- this.eventDispatcherTracker = new ServiceTracker(bundleContext, filter, null)
- {
- @Override
- public void removedService(ServiceReference reference, Object service)
- {
- ProxyListener.this.sessionDispatcher = null;
- ProxyListener.this.attributeDispatcher = null;
- ProxyListener.this.sessionIdDispatcher = null;
- super.removedService(reference, service);
- }
- };
+ this.eventDispatcherTracker = new EventDispatcherTracker(bundleContext);
this.eventDispatcherTracker.open();
}
catch (InvalidSyntaxException e)
@@ -187,49 +168,28 @@
private HttpSessionListener getSessionDispatcher()
{
- if (this.sessionDispatcher == null)
+ if (this.eventDispatcherTracker != null)
{
- final Object dispatcher = getDispatcher();
- if (dispatcher instanceof HttpSessionListener)
- {
- this.sessionDispatcher = (HttpSessionListener) dispatcher;
- }
+ return this.eventDispatcherTracker.getHttpSessionListener();
}
- return this.sessionDispatcher;
+ return null;
}
private HttpSessionIdListener getSessionIdDispatcher()
{
- if (this.sessionIdDispatcher == null)
+ if (this.eventDispatcherTracker != null)
{
- final Object dispatcher = getDispatcher();
- if (dispatcher instanceof HttpSessionIdListener)
- {
- this.sessionIdDispatcher = (HttpSessionIdListener) dispatcher;
- }
+ return this.eventDispatcherTracker.getHttpSessionIdListener();
}
- return this.sessionIdDispatcher;
+ return null;
}
private HttpSessionAttributeListener getAttributeDispatcher()
{
- if (this.attributeDispatcher == null)
+ if (this.eventDispatcherTracker != null)
{
- final Object dispatcher = getDispatcher();
- if (dispatcher instanceof HttpSessionAttributeListener)
- {
- this.attributeDispatcher = (HttpSessionAttributeListener) dispatcher;
- }
+ return this.eventDispatcherTracker.getHttpSessionAttributeListener();
}
- return this.attributeDispatcher;
- }
-
- private static Filter createFilter(BundleContext context, String filter) throws InvalidSyntaxException
- {
- StringBuffer str = new StringBuffer();
- str.append("(&(").append(Constants.OBJECTCLASS).append("=");
- str.append(EventListener.class.getName()).append(")");
- str.append(filter != null ? filter : DispatcherTracker.DEFAULT_FILTER).append(")");
- return context.createFilter(str.toString());
+ return null;
}
}
diff --git a/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/BridgeServiceTracker.java b/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/BridgeServiceTracker.java
new file mode 100644
index 0000000..36679ff
--- /dev/null
+++ b/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/BridgeServiceTracker.java
@@ -0,0 +1,81 @@
+/*
+ * 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.proxy.impl;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * @since 3.0.0
+ */
+public abstract class BridgeServiceTracker<T>
+ extends ServiceTracker<T, T>
+{
+ private final static String DEFAULT_FILTER = "(http.felix.dispatcher=*)";
+
+ private volatile T usedService;
+
+ public BridgeServiceTracker(final BundleContext context, final Class<?> objectClass)
+ throws InvalidSyntaxException
+ {
+ super(context, createFilter(context, objectClass), null);
+ }
+
+
+ protected abstract void setService(final T service);
+
+ protected abstract void unsetService();
+
+
+ @Override
+ public T addingService(final ServiceReference<T> ref)
+ {
+ final T service = super.addingService(ref);
+ if ( usedService == null )
+ {
+ this.usedService = service;
+ this.setService(service);
+ }
+
+ return service;
+ }
+
+ @Override
+ public void removedService(final ServiceReference<T> ref, final T service)
+ {
+ if ( service == usedService )
+ {
+ this.unsetService();
+ }
+
+ super.removedService(ref, service);
+ }
+
+ private static Filter createFilter(final BundleContext context, final Class<?> objectClass)
+ throws InvalidSyntaxException
+ {
+ StringBuffer str = new StringBuffer();
+ str.append("(&(").append(Constants.OBJECTCLASS).append("=");
+ str.append(objectClass.getName()).append(")");
+ str.append(DEFAULT_FILTER).append(")");
+ return context.createFilter(str.toString());
+ }
+}
diff --git a/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/EventDispatcherTracker.java b/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/EventDispatcherTracker.java
new file mode 100644
index 0000000..9c11700
--- /dev/null
+++ b/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/EventDispatcherTracker.java
@@ -0,0 +1,85 @@
+/*
+ * 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.proxy.impl;
+
+import java.util.EventListener;
+
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionIdListener;
+import javax.servlet.http.HttpSessionListener;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * @since 3.0.0
+ */
+public final class EventDispatcherTracker
+ extends BridgeServiceTracker<EventListener>
+{
+ private HttpSessionListener sessionListener;
+
+ private HttpSessionIdListener sessionIdListener;
+
+ private HttpSessionAttributeListener sessionAttributeListener;
+
+ public EventDispatcherTracker(final BundleContext context)
+ throws InvalidSyntaxException
+ {
+ super(context, EventListener.class);
+ }
+
+ @Override
+ protected void setService(final EventListener service)
+ {
+ if ( service instanceof HttpSessionListener )
+ {
+ this.sessionListener = (HttpSessionListener)service;
+ }
+ if ( service instanceof HttpSessionIdListener )
+ {
+ this.sessionIdListener = (HttpSessionIdListener)service;
+ }
+ if ( service instanceof HttpSessionAttributeListener )
+ {
+ this.sessionAttributeListener = (HttpSessionAttributeListener)service;
+ }
+ }
+
+ public HttpSessionListener getHttpSessionListener()
+ {
+ return this.sessionListener;
+ }
+
+ public HttpSessionIdListener getHttpSessionIdListener()
+ {
+ return this.sessionIdListener;
+ }
+
+ public HttpSessionAttributeListener getHttpSessionAttributeListener()
+ {
+ return this.sessionAttributeListener;
+ }
+
+ @Override
+ protected void unsetService()
+ {
+ sessionListener = null;
+ sessionIdListener = null;
+ sessionAttributeListener = null;
+ }
+}
diff --git a/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/ProxyServletContextListener.java b/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/ProxyServletContextListener.java
new file mode 100644
index 0000000..e31656c
--- /dev/null
+++ b/http/proxy/src/main/java/org/apache/felix/http/proxy/impl/ProxyServletContextListener.java
@@ -0,0 +1,219 @@
+/*
+ * 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.proxy.impl;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionIdListener;
+import javax.servlet.http.HttpSessionListener;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+
+/**
+ * The ProxyServletContextListener is a servlet context listener which will setup
+ * all required listeners for the http service implementation.
+ *
+ * @since 3.0.0
+ */
+@WebListener
+public class ProxyServletContextListener
+ implements ServletContextListener
+{
+
+ private volatile ServletContext servletContext;
+
+ private volatile EventDispatcherTracker eventDispatcherTracker;
+
+ // ---------- ServletContextListener
+
+ @Override
+ public void contextInitialized(final ServletContextEvent sce)
+ {
+ this.servletContext = sce.getServletContext();
+
+ // add all required listeners
+ this.servletContext.addListener(new HttpSessionListener()
+ {
+ private HttpSessionListener getHttpSessionListener()
+ {
+ final EventDispatcherTracker tracker = eventDispatcherTracker;
+ if ( tracker != null )
+ {
+ return tracker.getHttpSessionListener();
+ }
+ return null;
+ }
+
+ @Override
+ public void sessionCreated(final HttpSessionEvent se)
+ {
+ final HttpSessionListener sessionDispatcher = getHttpSessionListener();
+ if (sessionDispatcher != null)
+ {
+ sessionDispatcher.sessionCreated(se);
+ }
+ }
+
+ @Override
+ public void sessionDestroyed(final HttpSessionEvent se)
+ {
+ final HttpSessionListener sessionDispatcher = getHttpSessionListener();
+ if (sessionDispatcher != null)
+ {
+ sessionDispatcher.sessionDestroyed(se);
+ }
+ }
+ });
+ this.servletContext.addListener(new HttpSessionIdListener()
+ {
+ private HttpSessionIdListener getHttpSessionIdListener()
+ {
+ final EventDispatcherTracker tracker = eventDispatcherTracker;
+ if ( tracker != null )
+ {
+ return tracker.getHttpSessionIdListener();
+ }
+ return null;
+ }
+
+ @Override
+ public void sessionIdChanged(final HttpSessionEvent event, final String oldSessionId)
+ {
+ final HttpSessionIdListener sessionIdDispatcher = getHttpSessionIdListener();
+ if (sessionIdDispatcher != null)
+ {
+ sessionIdDispatcher.sessionIdChanged(event, oldSessionId);
+ }
+ }
+ });
+ this.servletContext.addListener(new HttpSessionAttributeListener()
+ {
+ private HttpSessionAttributeListener getHttpSessionAttributeListener()
+ {
+ final EventDispatcherTracker tracker = eventDispatcherTracker;
+ if ( tracker != null )
+ {
+ return tracker.getHttpSessionAttributeListener();
+ }
+ return null;
+ }
+
+ @Override
+ public void attributeAdded(final HttpSessionBindingEvent se)
+ {
+ final HttpSessionAttributeListener attributeDispatcher = getHttpSessionAttributeListener();
+ if (attributeDispatcher != null)
+ {
+ attributeDispatcher.attributeAdded(se);
+ }
+ }
+
+ @Override
+ public void attributeRemoved(final HttpSessionBindingEvent se)
+ {
+ final HttpSessionAttributeListener attributeDispatcher = getHttpSessionAttributeListener();
+ if (attributeDispatcher != null)
+ {
+ attributeDispatcher.attributeRemoved(se);
+ }
+ }
+
+ @Override
+ public void attributeReplaced(final HttpSessionBindingEvent se)
+ {
+ final HttpSessionAttributeListener attributeDispatcher = getHttpSessionAttributeListener();
+ if (attributeDispatcher != null)
+ {
+ attributeDispatcher.attributeReplaced(se);
+ }
+ }
+ });
+ this.servletContext.addListener(new ServletContextAttributeListener()
+ {
+ @Override
+ public void attributeAdded(final ServletContextAttributeEvent event)
+ {
+ if ( event.getName().equals(BundleContext.class.getName()) )
+ {
+ startTracker(event.getValue());
+ }
+ }
+
+ @Override
+ public void attributeRemoved(final ServletContextAttributeEvent event)
+ {
+ if ( event.getName().equals(BundleContext.class.getName()) )
+ {
+ stopTracker();
+ }
+ }
+
+ @Override
+ public void attributeReplaced(final ServletContextAttributeEvent event)
+ {
+ if ( event.getName().equals(BundleContext.class.getName()) )
+ {
+ stopTracker();
+ startTracker(event.getServletContext().getAttribute(event.getName()));
+ }
+ }
+ });
+ }
+
+ private void startTracker(final Object bundleContextAttr)
+ {
+ if (bundleContextAttr instanceof BundleContext)
+ {
+ try
+ {
+ final BundleContext bundleContext = (BundleContext) bundleContextAttr;
+ this.eventDispatcherTracker = new EventDispatcherTracker(bundleContext);
+ this.eventDispatcherTracker.open();
+ }
+ catch (final InvalidSyntaxException e)
+ {
+ // not expected for our simple filter
+ }
+ }
+ }
+
+ private void stopTracker()
+ {
+ if (this.eventDispatcherTracker != null)
+ {
+ this.eventDispatcherTracker.close();
+ this.eventDispatcherTracker = null;
+ }
+ }
+
+ @Override
+ public void contextDestroyed(final ServletContextEvent sce)
+ {
+ this.stopTracker();
+ this.servletContext = null;
+ }
+}