FELIX-4060 : Implement HTTP Service Update (RFC-189)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1656336 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
new file mode 100644
index 0000000..27fd5da
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
@@ -0,0 +1,36 @@
+/*
+ * 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.base.internal.runtime;
+
+import javax.servlet.ServletContextAttributeListener;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Info object for registered servlet context attribute listeners
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class ServletContextAttributeListenerInfo extends WhiteboardServiceInfo<ServletContextAttributeListener>
+{
+ public ServletContextAttributeListenerInfo(final ServiceReference<ServletContextAttributeListener> ref)
+ {
+ super(ref);
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
index 68b9366..4ba0741 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
@@ -18,14 +18,18 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.runtime.ContextInfo;
+import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
import org.osgi.framework.Bundle;
import org.osgi.service.http.context.ServletContextHelper;
@@ -41,8 +45,12 @@
/** The shared part of the servlet context. */
private final ServletContext sharedContext;
+ /** Servlet context listeners. */
private final Map<Long, ServletContextListener> listeners = new HashMap<Long, ServletContextListener>();
+ /** Servlet context attribute listeners. */
+ private final Map<Long, ServletContextAttributeListener> contextAttributeListeners = new ConcurrentHashMap<Long, ServletContextAttributeListener>();
+
/**
* Create new handler.
* @param info
@@ -51,7 +59,35 @@
public ContextHandler(final ContextInfo info, final ServletContext webContext)
{
this.info = info;
- this.sharedContext = new SharedServletContextImpl(webContext, info.getPrefix(), info.getName());
+ this.sharedContext = new SharedServletContextImpl(webContext,
+ info.getPrefix(),
+ info.getName(),
+ new ServletContextAttributeListener() {
+
+ @Override
+ public void attributeReplaced(final ServletContextAttributeEvent event) {
+ for(final ServletContextAttributeListener l : contextAttributeListeners.values())
+ {
+ l.attributeReplaced(event);
+ }
+ }
+
+ @Override
+ public void attributeRemoved(final ServletContextAttributeEvent event) {
+ for(final ServletContextAttributeListener l : contextAttributeListeners.values())
+ {
+ l.attributeReplaced(event);
+ }
+ }
+
+ @Override
+ public void attributeAdded(final ServletContextAttributeEvent event) {
+ for(final ServletContextAttributeListener l : contextAttributeListeners.values())
+ {
+ l.attributeReplaced(event);
+ }
+ }
+ });
}
/**
@@ -143,6 +179,24 @@
}
}
+ public void addListener(@Nonnull final Bundle bundle, @Nonnull final ServletContextAttributeListenerInfo info)
+ {
+ final ServletContextAttributeListener service = bundle.getBundleContext().getServiceObjects(info.getServiceReference()).getService();
+ if ( service != null )
+ {
+ this.contextAttributeListeners.put(info.getServiceId(), service);
+ }
+ }
+
+ public void removeListener(@Nonnull final Bundle bundle, @Nonnull final ServletContextAttributeListenerInfo info)
+ {
+ final ServletContextAttributeListener service = this.contextAttributeListeners.remove(info.getServiceId());
+ if ( service != null )
+ {
+ bundle.getBundleContext().getServiceObjects(info.getServiceReference()).ungetService(service);
+ }
+ }
+
private static final class ContextHolder
{
public long counter;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
index 41c2b0a..935d8e2 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
@@ -30,6 +30,7 @@
import org.apache.felix.http.base.internal.runtime.ContextInfo;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
import org.apache.felix.http.base.internal.runtime.ResourceInfo;
+import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
import org.apache.felix.http.base.internal.runtime.ServletInfo;
import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
@@ -316,6 +317,10 @@
{
this.httpService.registerResource(handler, (ResourceInfo)info);
}
+ else if ( info instanceof ServletContextAttributeListenerInfo )
+ {
+ handler.addListener(this.bundle, (ServletContextAttributeListenerInfo)info );
+ }
}
/**
@@ -337,5 +342,9 @@
{
this.httpService.unregisterResource(handler, (ResourceInfo)info);
}
+ else if ( info instanceof ServletContextAttributeListenerInfo )
+ {
+ handler.removeListener(this.bundle, (ServletContextAttributeListenerInfo)info );
+ }
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
index d7d1cdd..dd10996 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
@@ -31,6 +31,8 @@
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.SessionCookieConfig;
@@ -52,10 +54,12 @@
private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
private final String contextPath;
private final String name;
+ private final ServletContextAttributeListener attributeListener;
public SharedServletContextImpl(final ServletContext webContext,
final String name,
- final String prefix)
+ final String prefix,
+ final ServletContextAttributeListener servletContextAttributeListener)
{
this.context = webContext;
if ( prefix == null )
@@ -67,6 +71,7 @@
this.contextPath = webContext.getContextPath() + prefix;
}
this.name = name;
+ this.attributeListener = servletContextAttributeListener;
}
@Override
@@ -384,11 +389,11 @@
@Override
public void removeAttribute(final String name)
{
- Object oldValue = this.attributes.remove(name);
+ final Object oldValue = this.attributes.remove(name);
if (oldValue != null)
{
- //this.attributeListener.attributeRemoved(new ServletContextAttributeEvent(this, name, oldValue));
+ this.attributeListener.attributeRemoved(new ServletContextAttributeEvent(this, name, oldValue));
}
}
@@ -405,11 +410,11 @@
if (oldValue == null)
{
- //this.attributeListener.attributeAdded(new ServletContextAttributeEvent(this, name, value));
+ this.attributeListener.attributeAdded(new ServletContextAttributeEvent(this, name, value));
}
else
{
- //this.attributeListener.attributeReplaced(new ServletContextAttributeEvent(this, name, oldValue));
+ this.attributeListener.attributeReplaced(new ServletContextAttributeEvent(this, name, oldValue));
}
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.java
new file mode 100644
index 0000000..9df9831
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextAttributeListenerTracker.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.base.internal.whiteboard.tracker;
+
+import javax.servlet.ServletContextAttributeListener;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
+import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public final class ServletContextAttributeListenerTracker extends AbstractReferenceTracker<ServletContextAttributeListener>
+{
+ private final ServletContextHelperManager contextManager;
+
+ /** TODO Currently under discussion. */
+ private static final String OPT_IN_PROP = "osgi.http.whiteboard.listener";
+
+ private static org.osgi.framework.Filter createFilter(final BundleContext btx)
+ {
+ try
+ {
+ return btx.createFilter(String.format("(&(objectClass=%s)(%s=*))",
+ ServletContextAttributeListener.class.getName(),
+ OPT_IN_PROP));
+ }
+ catch ( final InvalidSyntaxException ise)
+ {
+ // we can safely ignore it as the above filter is a constant
+ }
+ return null; // we never get here - and if we get an NPE which is fine
+ }
+
+ public ServletContextAttributeListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
+ {
+ super(context, createFilter(context));
+ this.contextManager = manager;
+ }
+
+ @Override
+ protected void added(final ServiceReference<ServletContextAttributeListener> ref)
+ {
+ final ServletContextAttributeListenerInfo info = new ServletContextAttributeListenerInfo(ref);
+
+ if ( info.isValid() )
+ {
+ this.contextManager.addWhiteboardService(info);
+ }
+ else
+ {
+ SystemLogger.debug("Ignoring ServletContextAttributeListenerInfo service " + ref);
+ }
+ }
+
+ @Override
+ protected void removed(final ServiceReference<ServletContextAttributeListener> ref)
+ {
+ final ServletContextAttributeListenerInfo info = new ServletContextAttributeListenerInfo(ref);
+
+ if ( info.isValid() )
+ {
+ this.contextManager.removeWhiteboardService(info);
+ }
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
index e7632b3..37306ef 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
@@ -64,7 +64,7 @@
}
else
{
- SystemLogger.debug("Ignoring Filter service " + ref);
+ SystemLogger.debug("Ignoring ServletContextListenerInfo service " + ref);
}
}