cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cschnei...@apache.org
Subject [3/3] cxf-dosgi git commit: [DOSGI-242] Extract common module, use DS
Date Fri, 01 Jul 2016 19:57:00 GMT
[DOSGI-242] Extract common module, use DS


Project: http://git-wip-us.apache.org/repos/asf/cxf-dosgi/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-dosgi/commit/d2a3c75f
Tree: http://git-wip-us.apache.org/repos/asf/cxf-dosgi/tree/d2a3c75f
Diff: http://git-wip-us.apache.org/repos/asf/cxf-dosgi/diff/d2a3c75f

Branch: refs/heads/master
Commit: d2a3c75f3a6496ec52961ee7238fcf519bd9a8a5
Parents: 79bb9a4
Author: Christian Schneider <chris@die-schneider.net>
Authored: Fri Jul 1 21:56:50 2016 +0200
Committer: Christian Schneider <chris@die-schneider.net>
Committed: Fri Jul 1 21:56:50 2016 +0200

----------------------------------------------------------------------
 common/bnd.bnd                                  |   6 +
 common/pom.xml                                  |  78 +++++
 .../common/httpservice/HttpServiceManager.java  | 179 ++++++++++++
 .../dosgi/common/httpservice/LocalHostUtil.java |  92 ++++++
 .../SecurityDelegatingHttpContext.java          | 133 +++++++++
 .../common/intent/DefaultIntentMapFactory.java  |  52 ++++
 .../cxf/dosgi/common/intent/IntentManager.java  |  35 +++
 .../dosgi/common/intent/IntentManagerImpl.java  | 214 ++++++++++++++
 .../cxf/dosgi/common/intent/IntentMap.java      |  62 ++++
 .../cxf/dosgi/common/intent/IntentTracker.java  |  61 ++++
 .../cxf/dosgi/common/util/ClassUtils.java       |  86 ++++++
 .../apache/cxf/dosgi/common/util/OsgiUtils.java |  78 +++++
 .../cxf/dosgi/common/util/ServerWrapper.java    |  49 ++++
 .../cxf/dosgi/common/util/StringPlus.java       |  72 +++++
 .../httpservice/HttpServiceManagerTest.java     | 118 ++++++++
 .../SecurityDelegatingHttpContextTest.java      | 267 ++++++++++++++++++
 .../dosgi/common/qos/IntentManagerImplTest.java | 282 +++++++++++++++++++
 .../cxf/dosgi/common/qos/IntentMapTest.java     |  42 +++
 .../cxf/dosgi/common/qos/IntentTrackerTest.java |  82 ++++++
 .../cxf/dosgi/common/util/ClassUtilsTest.java   | 114 ++++++++
 .../cxf/dosgi/common/util/OsgiUtilsTest.java    |  70 +++++
 .../apache/cxf/dosgi/common/util/Provider.java  |  23 ++
 cxf-dsw/bnd.bnd                                 |   3 +-
 cxf-dsw/pom.xml                                 |   6 +
 .../dsw/handlers/CXFDistributionProvider.java   |  71 ++++-
 .../AbstractPojoConfigurationTypeHandler.java   |  36 ++-
 .../pojo/PojoConfigurationTypeHandler.java      |   4 +-
 .../pojo/WsdlConfigurationTypeHandler.java      |   6 +-
 .../rest/JaxRSPojoConfigurationTypeHandler.java |   8 +-
 .../cxf/dosgi/dsw/handlers/rest/JaxRSUtils.java |   4 +-
 .../dsw/httpservice/HttpServiceManager.java     | 176 ------------
 .../dosgi/dsw/httpservice/LocalHostUtil.java    |  92 ------
 .../SecurityDelegatingHttpContext.java          | 133 ---------
 .../apache/cxf/dosgi/dsw/osgi/Activator.java    | 153 ----------
 .../apache/cxf/dosgi/dsw/osgi/Constants.java    |  70 +----
 .../dosgi/dsw/qos/DefaultIntentMapFactory.java  |  52 ----
 .../apache/cxf/dosgi/dsw/qos/IntentManager.java |  31 --
 .../cxf/dosgi/dsw/qos/IntentManagerImpl.java    | 155 ----------
 .../org/apache/cxf/dosgi/dsw/qos/IntentMap.java |  62 ----
 .../apache/cxf/dosgi/dsw/qos/IntentTracker.java |  62 ----
 .../apache/cxf/dosgi/dsw/qos/IntentUtils.java   |  86 ------
 .../apache/cxf/dosgi/dsw/util/ClassUtils.java   |  86 ------
 .../apache/cxf/dosgi/dsw/util/OsgiUtils.java    |  78 -----
 .../cxf/dosgi/dsw/util/ServerWrapper.java       |  49 ----
 .../apache/cxf/dosgi/dsw/util/StringPlus.java   |  72 -----
 .../org/apache/cxf/dosgi/dsw/ActivatorTest.java |  67 -----
 .../org/apache/cxf/dosgi/dsw/TestUtils.java     |  37 ---
 .../handlers/CXFDistributionProviderTest.java   |  22 +-
 .../cxf/dosgi/dsw/handlers/ClassUtilsTest.java  | 116 --------
 .../pojo/PojoConfigurationTypeHandlerTest.java  |  35 ++-
 .../dsw/httpservice/HttpServiceManagerTest.java | 125 --------
 .../SecurityDelegatingHttpContextTest.java      | 267 ------------------
 .../dosgi/dsw/qos/IntentManagerImplTest.java    | 278 ------------------
 .../apache/cxf/dosgi/dsw/qos/IntentMapTest.java |  41 ---
 .../cxf/dosgi/dsw/qos/IntentTrackerTest.java    |  80 ------
 .../cxf/dosgi/dsw/qos/IntentUtilsTest.java      |  70 -----
 .../cxf/dosgi/dsw/util/OsgiUtilsTest.java       |  70 -----
 .../org/apache/cxf/dosgi/dsw/util/Provider.java |  23 --
 .../features/src/main/resources/features.xml    |   6 +-
 pom.xml                                         |   1 +
 60 files changed, 2346 insertions(+), 2582 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/bnd.bnd
----------------------------------------------------------------------
diff --git a/common/bnd.bnd b/common/bnd.bnd
new file mode 100644
index 0000000..9fc9a8c
--- /dev/null
+++ b/common/bnd.bnd
@@ -0,0 +1,6 @@
+Import-Package: javax.servlet;version='[2,4)', javax.servlet.http;version='[2,4)', *
+Export-Package: \
+	org.apache.cxf.dosgi.common.httpservice,\
+	org.apache.cxf.dosgi.common.util,\
+	org.apache.cxf.dosgi.common.intent
+Private-Package: org.apache.cxf.dosgi.common.osgi

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/pom.xml
----------------------------------------------------------------------
diff --git a/common/pom.xml b/common/pom.xml
new file mode 100644
index 0000000..dd5ea46
--- /dev/null
+++ b/common/pom.xml
@@ -0,0 +1,78 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>cxf-dosgi-ri-common</artifactId>
+    <packaging>bundle</packaging>
+    <name>CXF dOSGi Common</name>
+
+    <parent>
+        <groupId>org.apache.cxf.dosgi</groupId>
+        <artifactId>cxf-dosgi-ri-parent</artifactId>
+        <version>1.9-SNAPSHOT</version>
+        <relativePath>../parent/pom.xml</relativePath>
+    </parent>
+
+    <properties>
+        <topDirectoryLocation>..</topDirectoryLocation>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-core</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxws</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+		<dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-client</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-databinding-aegis</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-extension-providers</artifactId>
+            <version>${cxf.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-servlet_${servlet.version}_spec</artifactId>
+            <version>1.0</version>
+        </dependency>
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManager.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManager.java b/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManager.java
new file mode 100644
index 0000000..b129514
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManager.java
@@ -0,0 +1,179 @@
+/**
+ * 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.cxf.dosgi.common.httpservice;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.http.DestinationRegistryImpl;
+import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceException;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+           configurationPid = "cxf-dsw",
+           service = HttpServiceManager.class
+           )
+public class HttpServiceManager {
+    /**
+     * Prefix to create an absolute URL from a relative URL.
+     * See HttpServiceManager.getAbsoluteAddress
+     *
+     * Defaults to: http://<host name>:8181
+     */
+    public static final String KEY_HTTP_BASE = "httpBase";
+    public static final String KEY_CXF_SERVLET_ALIAS = "cxfServletAlias";
+    public static final String DEFAULT_CXF_SERVLET_ALIAS = "/cxf";
+    private static final Logger LOG = LoggerFactory.getLogger(HttpServiceManager.class);
+    
+    private Map<Long, String> exportedAliases = Collections.synchronizedMap(new HashMap<Long, String>());
+    private String httpBase;
+    private String cxfServletAlias;
+    private HttpService httpService;
+    private BundleContext context;
+
+    @SuppressWarnings("unchecked")
+    @Activate
+    public void activate(ComponentContext compContext) {
+        Dictionary<String, String> config = compContext.getProperties();
+        initFromConfig(config);
+        this.context = compContext.getBundleContext();
+    }
+
+    void initFromConfig(Dictionary<String, String> config) {
+        if (config == null) {
+            config = new Hashtable<String, String>();
+        }
+        this.httpBase = getWithDefault(config.get(KEY_HTTP_BASE), "http://" + LocalHostUtil.getLocalIp() + ":8181");
+        this.cxfServletAlias = getWithDefault(config.get(KEY_CXF_SERVLET_ALIAS), "/cxf");
+    }
+
+    private String getWithDefault(String value, String defaultValue) {
+        return value == null ? defaultValue : value;
+    }
+
+    public Bus registerServlet(Bus bus, String contextRoot, BundleContext callingContext, Long sid) {
+        bus.setExtension(new DestinationRegistryImpl(), DestinationRegistry.class);
+        CXFNonSpringServlet cxf = new CXFNonSpringServlet();
+        cxf.setBus(bus);
+        try {
+            HttpContext httpContext1 = httpService.createDefaultHttpContext();
+            HttpContext httpContext = new SecurityDelegatingHttpContext(callingContext, httpContext1);
+            httpService.registerServlet(contextRoot, cxf, new Hashtable<String, String>(),
+                                       httpContext);
+
+            registerUnexportHook(sid, contextRoot);
+
+            LOG.info("Successfully registered CXF DOSGi servlet at " + contextRoot);
+        } catch (Exception e) {
+            throw new ServiceException("CXF DOSGi: problem registering CXF HTTP Servlet", e);
+        }
+        return bus;
+    }
+
+    /**
+     * This listens for service removal events and "un-exports" the service
+     * from the HttpService.
+     *
+     * @param sref the service reference to track
+     * @param alias the HTTP servlet context alias
+     */
+    private void registerUnexportHook(Long sid, String alias) {
+        LOG.debug("Registering service listener for service with ID {}", sid);
+
+        String previous = exportedAliases.put(sid, alias);
+        if (previous != null) {
+            LOG.warn("Overwriting service export for service with ID {}", sid);
+        }
+
+        try {
+            Filter f = context.createFilter("(" + org.osgi.framework.Constants.SERVICE_ID + "=" + sid + ")");
+            if (f != null) {
+                context.addServiceListener(new UnregisterListener(), f.toString());
+            } else {
+                LOG.warn("Service listener could not be started. The service will not be automatically unexported.");
+            }
+        } catch (InvalidSyntaxException e) {
+            LOG.warn("Service listener could not be started. The service will not be automatically unexported.", e);
+        }
+    }
+
+    public String getDefaultAddress(Class<?> type) {
+        return "/" + type.getName().replace('.', '/');
+    }
+
+    public String getAbsoluteAddress(String contextRoot, String relativeEndpointAddress) {
+        if (relativeEndpointAddress.startsWith("http")) {
+            return relativeEndpointAddress;
+        }
+        String effContextRoot = contextRoot == null ? cxfServletAlias : contextRoot;
+        return this.httpBase + effContextRoot + relativeEndpointAddress;
+    }
+
+    private final class UnregisterListener implements ServiceListener {
+
+        public void serviceChanged(ServiceEvent event) {
+            if (!(event.getType() == ServiceEvent.UNREGISTERING)) {
+                return;
+            }
+            final ServiceReference<?> sref = event.getServiceReference();
+            final Long sid = (Long) sref.getProperty(org.osgi.framework.Constants.SERVICE_ID);
+            final String alias = exportedAliases.remove(sid);
+            if (alias == null) {
+                LOG.error("Unable to unexport HTTP servlet for service class '{}',"
+                        + " service-id {}: no servlet alias found",
+                        sref.getProperty(org.osgi.framework.Constants.OBJECTCLASS), sid);
+                return;
+            }
+            LOG.debug("Unexporting HTTP servlet for alias '{}'", alias);
+            try {
+                httpService.unregister(alias);
+            } catch (Exception e) {
+                LOG.warn("An exception occurred while unregistering service for HTTP servlet alias '{}'", alias, e);
+            }
+        }
+    }
+    
+    public void setContext(BundleContext context) {
+        this.context = context;
+    }
+    
+    @Reference
+    public void setHttpService(HttpService httpService) {
+        this.httpService = httpService;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/LocalHostUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/LocalHostUtil.java b/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/LocalHostUtil.java
new file mode 100644
index 0000000..0ac245d
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/LocalHostUtil.java
@@ -0,0 +1,92 @@
+/**
+ * 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.cxf.dosgi.common.httpservice;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * Utility methods to get the local address even on a linux host.
+ */
+final class LocalHostUtil {
+
+    private LocalHostUtil() {
+        // Util Class
+    }
+
+    /**
+     * Returns an InetAddress representing the address of the localhost. Every
+     * attempt is made to find an address for this host that is not the loopback
+     * address. If no other address can be found, the loopback will be returned.
+     *
+     * @return InetAddress the address of localhost
+     * @throws UnknownHostException if there is a problem determining the address
+     */
+    public static InetAddress getLocalHost() throws UnknownHostException {
+        InetAddress localHost = InetAddress.getLocalHost();
+        if (!localHost.isLoopbackAddress()) {
+            return localHost;
+        }
+        InetAddress[] addrs = getAllLocalUsingNetworkInterface();
+        for (InetAddress addr : addrs) {
+            if (!addr.isLoopbackAddress() && !addr.getHostAddress().contains(":")) {
+                return addr;
+            }
+        }
+        return localHost;
+    }
+
+    /**
+     * Utility method that delegates to the methods of NetworkInterface to
+     * determine addresses for this machine.
+     *
+     * @return all addresses found from the NetworkInterfaces
+     * @throws UnknownHostException if there is a problem determining addresses
+     */
+    private static InetAddress[] getAllLocalUsingNetworkInterface() throws UnknownHostException {
+        try {
+            List<InetAddress> addresses = new ArrayList<InetAddress>();
+            Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
+            while (e.hasMoreElements()) {
+                NetworkInterface ni = e.nextElement();
+                for (Enumeration<InetAddress> e2 = ni.getInetAddresses(); e2.hasMoreElements();) {
+                    addresses.add(e2.nextElement());
+                }
+            }
+            return addresses.toArray(new InetAddress[] {});
+        } catch (SocketException ex) {
+            throw new UnknownHostException("127.0.0.1");
+        }
+    }
+
+    public static String getLocalIp() {
+        String localIP;
+        try {
+            localIP = getLocalHost().getHostAddress();
+        } catch (Exception e) {
+            localIP = "localhost";
+        }
+        return localIP;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContext.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContext.java b/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContext.java
new file mode 100644
index 0000000..4eba758
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContext.java
@@ -0,0 +1,133 @@
+/**
+ * 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.cxf.dosgi.common.httpservice;
+
+import java.io.IOException;
+import java.net.URL;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <p>
+ * An HttpContext that delegates to another HttpContext for all things other than security. This implementation handles
+ * security by delegating to a {@link FilterChain} based on the set of {@link Filter}s registered with a
+ * {@link #FILTER_PROP} property.
+ * </p>
+ * <p>
+ * If the {@link BundleContext} contains a {@link #FILTER_REQUIRED_PROP} property with value "true", requests will not
+ * be allowed until at least one {@link Filter} with a {@link #FILTER_PROP} property is registered.
+ * </p>
+ */
+class SecurityDelegatingHttpContext implements HttpContext {
+
+    public static final String FILTER_PROP = "org.apache.cxf.httpservice.filter";
+    public static final String FILTER_REQUIRED_PROP = "org.apache.cxf.httpservice.requirefilter";
+    private static final Logger LOG = LoggerFactory.getLogger(SecurityDelegatingHttpContext.class);
+    private static final String FILTER_FILTER = "(" + FILTER_PROP + "=*)";
+
+    BundleContext bundleContext;
+    HttpContext delegate;
+    boolean requireFilter;
+
+    SecurityDelegatingHttpContext(BundleContext bundleContext, HttpContext delegate) {
+        this.bundleContext = bundleContext;
+        this.delegate = delegate;
+        requireFilter = Boolean.TRUE.toString().equalsIgnoreCase(bundleContext.getProperty(FILTER_REQUIRED_PROP));
+    }
+
+    public String getMimeType(String name) {
+        return delegate.getMimeType(name);
+    }
+
+    public URL getResource(String name) {
+        return delegate.getResource(name);
+    }
+
+    @SuppressWarnings({
+     "unchecked", "rawtypes"
+    })
+    public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        ServiceReference[] refs;
+        try {
+            refs = bundleContext.getServiceReferences(Filter.class.getName(), FILTER_FILTER);
+        } catch (InvalidSyntaxException e) {
+            LOG.warn(e.getMessage(), e);
+            return false;
+        }
+        if (refs == null || refs.length == 0) {
+            LOG.info("No filter registered.");
+            return !requireFilter;
+        }
+        Filter[] filters = new Filter[refs.length];
+        try {
+            for (int i = 0; i < refs.length; i++) {
+                filters[i] = (Filter)bundleContext.getService(refs[i]);
+            }
+            try {
+                new Chain(filters).doFilter(request, response);
+                return !response.isCommitted();
+            } catch (ServletException e) {
+                LOG.warn(e.getMessage(), e);
+                return false;
+            }
+        } finally {
+            for (int i = 0; i < refs.length; i++) {
+                if (filters[i] != null) {
+                    bundleContext.ungetService(refs[i]);
+                }
+            }
+        }
+    }
+}
+
+/**
+ * A {@link FilterChain} composed of {@link Filter}s with the
+ */
+class Chain implements FilterChain {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Chain.class);
+
+    int current;
+    final Filter[] filters;
+
+    Chain(Filter[] filters) {
+        this.filters = filters;
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
+        if (current < filters.length && !response.isCommitted()) {
+            Filter filter = filters[current++];
+            LOG.info("doFilter() on {}", filter);
+            filter.doFilter(request, response, this);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/intent/DefaultIntentMapFactory.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/DefaultIntentMapFactory.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/DefaultIntentMapFactory.java
new file mode 100644
index 0000000..395fe46
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/DefaultIntentMapFactory.java
@@ -0,0 +1,52 @@
+/**
+ * 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.cxf.dosgi.common.intent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cxf.binding.soap.Soap11;
+import org.apache.cxf.binding.soap.Soap12;
+import org.apache.cxf.binding.soap.SoapBindingConfiguration;
+import org.apache.cxf.binding.soap.SoapVersion;
+import org.apache.cxf.feature.LoggingFeature;
+
+public class DefaultIntentMapFactory {
+
+    public Map<String, Object> create() {
+        Map<String, Object> intentMap = new HashMap<String, Object>();
+        intentMap.put("logging", getLoggingFeature());
+        Object soap11 = getSoapBinding(Soap11.getInstance());
+        intentMap.put("SOAP", soap11);
+        intentMap.put("SOAP.1_1", soap11);
+        intentMap.put("SOAP.1_2", getSoapBinding(Soap12.getInstance()));
+        intentMap.put("HTTP", "PROVIDED");
+        return intentMap;
+    }
+
+    private Object getLoggingFeature() {
+        return new LoggingFeature();
+    }
+
+    private Object getSoapBinding(SoapVersion soapVersion) {
+        SoapBindingConfiguration soapBindingConfig = new SoapBindingConfiguration();
+        soapBindingConfig.setVersion(soapVersion);
+        return soapBindingConfig;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java
new file mode 100644
index 0000000..32eedab
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java
@@ -0,0 +1,35 @@
+/**
+ * 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.cxf.dosgi.common.intent;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.endpoint.AbstractEndpointFactory;
+import org.apache.cxf.feature.Feature;
+
+public interface IntentManager {
+    @Deprecated
+    String EXPORTED_INTENTS_OLD = "osgi.remote.requires.intents";
+
+    String INTENT_NAME_PROP = "org.apache.cxf.dosgi.IntentName";
+
+    String[] applyIntents(List<Feature> features, AbstractEndpointFactory factory, Map<String, Object> props);
+    void assertAllIntentsSupported(Map<String, Object> serviceProperties);
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManagerImpl.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManagerImpl.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManagerImpl.java
new file mode 100644
index 0000000..2775086
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManagerImpl.java
@@ -0,0 +1,214 @@
+/**
+ * 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.cxf.dosgi.common.intent;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.aries.rsa.spi.IntentUnsatisfiedException;
+import org.apache.cxf.binding.BindingConfiguration;
+import org.apache.cxf.dosgi.common.util.OsgiUtils;
+import org.apache.cxf.endpoint.AbstractEndpointFactory;
+import org.apache.cxf.feature.Feature;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = IntentManager.class)
+public class IntentManagerImpl implements IntentManager {
+
+    static final Logger LOG = LoggerFactory.getLogger(IntentManagerImpl.class);
+    private static final String PROVIDED_INTENT_VALUE = "PROVIDED";
+    private static final int DEFAULT_INTENT_TIMEOUT = 30000;
+
+    private final IntentMap intentMap;
+    private final long maxIntentWaitTime;
+    private IntentTracker tracker;
+
+    public IntentManagerImpl() {
+        this(DEFAULT_INTENT_TIMEOUT);
+    }
+
+    public IntentManagerImpl(int maxIntentWaitTime) {
+        this(new IntentMap(new DefaultIntentMapFactory().create()), maxIntentWaitTime);
+    }
+    
+    public IntentManagerImpl(IntentMap intentMap) {
+        this(intentMap, DEFAULT_INTENT_TIMEOUT);
+    }
+
+    // For test
+    public IntentManagerImpl(IntentMap intentMap, int maxIntentWaitTime) {
+        this.maxIntentWaitTime = maxIntentWaitTime;
+        this.intentMap = intentMap;
+    }
+
+    
+    @Activate
+    public void activate(BundleContext context) {
+        tracker = new IntentTracker(context, this.intentMap);
+        tracker.open();
+    }
+    
+    @Deactivate
+    public void deactivate() {
+        tracker.close();
+    }
+
+    public String[] applyIntents(List<Feature> features, AbstractEndpointFactory factory,
+                                 Map<String, Object> props) throws IntentUnsatisfiedException {
+        Set<String> requestedIntents = IntentManagerImpl.getRequestedIntents(props);
+        Set<String> appliedIntents = new HashSet<String>();
+        appliedIntents.addAll(reverseLookup(intentMap, PROVIDED_INTENT_VALUE));
+        boolean bindingApplied = false;
+        for (String intentName : requestedIntents) {
+            bindingApplied |= processIntent(features, factory, intentName, intentMap.get(intentName));
+            appliedIntents.add(intentName);
+        }
+        if (!bindingApplied) {
+            String defaultBindingName = "SOAP";
+            processIntent(features, factory, defaultBindingName, intentMap.get(defaultBindingName));
+            appliedIntents.add(defaultBindingName);
+        }
+        appliedIntents.addAll(addSynonymIntents(appliedIntents, intentMap));
+        return appliedIntents.toArray(new String[appliedIntents.size()]);
+    }
+    
+    private static Set<String> getRequestedIntents(Map<String, Object> sd) {
+        Collection<String> intents = OsgiUtils.getMultiValueProperty(sd.get(RemoteConstants.SERVICE_EXPORTED_INTENTS));
+        Collection<String> intents2
+            = OsgiUtils.getMultiValueProperty(sd.get(RemoteConstants.SERVICE_EXPORTED_INTENTS_EXTRA));
+        @SuppressWarnings("deprecation")
+        Collection<String> oldIntents = OsgiUtils.getMultiValueProperty(sd.get(IntentManager.EXPORTED_INTENTS_OLD));
+        Set<String> allIntents = new HashSet<String>();
+        if (intents != null) {
+            allIntents.addAll(parseIntents(intents));
+        }
+        if (intents2 != null) {
+            allIntents.addAll(parseIntents(intents2));
+        }
+        if (oldIntents != null) {
+            allIntents.addAll(parseIntents(oldIntents));
+        }
+
+        return allIntents;
+    }
+
+    private static Collection<String> parseIntents(Collection<String> intents) {
+        List<String> parsed = new ArrayList<String>();
+        for (String intent : intents) {
+            parsed.addAll(Arrays.asList(intent.split("[ ]")));
+        }
+        return parsed;
+    }
+
+    private boolean processIntent(List<Feature> features, AbstractEndpointFactory factory,
+                                  String intentName, Object intent) throws IntentUnsatisfiedException {
+        if (intent instanceof String) {
+            if (PROVIDED_INTENT_VALUE.equalsIgnoreCase((String) intent)) {
+                return false;
+            }
+        } else if (intent instanceof BindingConfiguration) {
+            BindingConfiguration bindingCfg = (BindingConfiguration)intent;
+            LOG.info("Applying intent: " + intentName + " via binding config: " + bindingCfg);
+            factory.setBindingConfig(bindingCfg);
+            return true;
+        } else if (intent instanceof Feature) {
+            Feature feature = (Feature) intent;
+            LOG.info("Applying intent: " + intentName + " via feature: " + feature);
+            features.add(feature);
+            return false;
+        } else {
+            LOG.info("No mapping for intent: " + intentName);
+            throw new IntentUnsatisfiedException(intentName);
+        }
+        return false;
+    }
+
+    private static Collection<String> addSynonymIntents(Collection<String> appliedIntents,
+                                                 IntentMap map) {
+        // E.g. SOAP and SOAP.1_1 are synonyms
+        List<Object> values = new ArrayList<Object>();
+        for (String key : appliedIntents) {
+            values.add(map.get(key));
+        }
+        return reverseLookup(map, values);
+    }
+
+    private static Collection<String> reverseLookup(IntentMap im, Object obj) {
+        return reverseLookup(im, Collections.singleton(obj));
+    }
+
+    /**
+     * Retrieves all keys whose mapped values are found in the given collection.
+     *
+     * @param im an intent map
+     * @param values a collection of potential values
+     * @return all keys whose mapped values are found in the given collection
+     */
+    private static Collection<String> reverseLookup(IntentMap im, Collection<?> values) {
+        Set<String> intentsFound = new HashSet<String>();
+        for (Map.Entry<String, Object> entry : im.entrySet()) {
+            if (values.contains(entry.getValue())) {
+                intentsFound.add(entry.getKey());
+            }
+        }
+        return intentsFound;
+    }
+
+    public void assertAllIntentsSupported(Map<String, Object> serviceProperties) {
+        long endTime = System.currentTimeMillis() + maxIntentWaitTime;
+        Set<String> requiredIntents = IntentManagerImpl.getRequestedIntents(serviceProperties);
+        List<String> unsupportedIntents = new ArrayList<String>();
+        do {
+            unsupportedIntents.clear();
+            for (String ri : requiredIntents) {
+                if (!intentMap.containsKey(ri)) {
+                    unsupportedIntents.add(ri);
+                }
+            }
+            long remainingSeconds = (endTime - System.currentTimeMillis()) / 1000;
+            if (!unsupportedIntents.isEmpty() && remainingSeconds > 0) {
+                LOG.debug("Waiting for custom intents " + unsupportedIntents + " timeout in " + remainingSeconds);
+                try {
+                    synchronized (intentMap) {
+                        intentMap.wait(1000);
+                    }
+                } catch (InterruptedException e) {
+                    LOG.warn(e.getMessage(), e);
+                }
+            }
+        } while (!unsupportedIntents.isEmpty() && System.currentTimeMillis() < endTime);
+
+        if (!unsupportedIntents.isEmpty()) {
+            throw new RuntimeException("service cannot be exported because the following "
+                                       + "intents are not supported by this RSA: " + unsupportedIntents);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentMap.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentMap.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentMap.java
new file mode 100644
index 0000000..9539c95
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentMap.java
@@ -0,0 +1,62 @@
+/**
+ * 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.cxf.dosgi.common.intent;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Maps intent names to intent objects
+ * An intent object can be a Feature, a BindingConfiguration or a String
+ *
+ * Also supports a default intent map. Custom intents can override the defaults
+ */
+public class IntentMap extends ConcurrentHashMap<String, Object> {
+
+    private static final long serialVersionUID = 2606460607920520767L;
+    private Map<String, Object> defaultMap;
+
+    public IntentMap() {
+        this(new HashMap<String, Object>());
+    }
+
+    public IntentMap(Map<String, Object> defaultMap) {
+        this.defaultMap = defaultMap;
+        putAll(defaultMap);
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        Object result = super.put(key, value);
+        synchronized (this) {
+            notifyAll();
+        }
+        return result;
+    }
+
+    @Override
+    public Object remove(Object key) {
+        Object old = super.remove(key);
+        if (defaultMap.containsKey(key)) {
+            put((String)key, defaultMap.get(key));
+        }
+        return old;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentTracker.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentTracker.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentTracker.java
new file mode 100644
index 0000000..678e9e5
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentTracker.java
@@ -0,0 +1,61 @@
+/**
+ * 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.cxf.dosgi.common.intent;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class IntentTracker extends ServiceTracker {
+
+    private final IntentMap intentMap;
+
+    
+    public IntentTracker(BundleContext context, IntentMap intentMap) {
+        super(context, getFilter(context), null);
+        this.intentMap = intentMap;
+    }
+
+    static Filter getFilter(BundleContext context) {
+        try {
+            return context.createFilter("(" + IntentManager.INTENT_NAME_PROP + "=*)");
+        } catch (InvalidSyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference) {
+        String intentName = (String) reference.getProperty(IntentManager.INTENT_NAME_PROP);
+        Object intent = super.addingService(reference);
+        IntentManagerImpl.LOG.info("Adding custom intent " + intentName);
+        intentMap.put(intentName, intent);
+        return intent;
+    }
+
+    @Override
+    public void removedService(ServiceReference reference, Object service) {
+        String intentName = (String) reference.getProperty(IntentManager.INTENT_NAME_PROP);
+        intentMap.remove(intentName);
+        super.removedService(reference, service);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/util/ClassUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/util/ClassUtils.java b/common/src/main/java/org/apache/cxf/dosgi/common/util/ClassUtils.java
new file mode 100644
index 0000000..9190b6c
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/util/ClassUtils.java
@@ -0,0 +1,86 @@
+/**
+ * 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.cxf.dosgi.common.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ClassUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ClassUtils.class);
+
+    private ClassUtils() {
+    }
+
+    public static List<Object> loadProviderClasses(BundleContext callingContext,
+                                                   Map<String, Object> sd, String propName) {
+        Object serviceProviders = sd.get(propName);
+        if (serviceProviders != null) {
+            if (serviceProviders.getClass().isArray()) {
+                if (serviceProviders.getClass().getComponentType() == String.class) {
+                    return loadProviders(callingContext, (String[])serviceProviders);
+                } else {
+                    return Arrays.asList((Object[])serviceProviders);
+                }
+            } else if (serviceProviders.getClass() == String.class) {
+                String[] classNames = serviceProviders.toString().split(",");
+                return loadProviders(callingContext, classNames);
+            } else if (serviceProviders instanceof List) { 
+                List<Object> list = CastUtils.cast((List<?>)serviceProviders);
+                if (!list.isEmpty()) {
+                    List<Object> providers;
+                    if (list.get(0).getClass() == String.class) {
+                        providers = loadProviders(callingContext, list.toArray(new String[]{}));
+                    } else {
+                        providers = list;
+                    }
+                    return providers;
+                }
+            } else {
+                return Arrays.asList(serviceProviders);
+            }
+        }
+        return Collections.emptyList();
+        
+    }
+
+    private static List<Object> loadProviders(BundleContext callingContext, String[] classNames) {
+        List<Object> providers = new ArrayList<Object>();
+        for (String className : classNames) {
+            try {
+                String realName = className.trim();
+                if (!realName.isEmpty()) {
+                    Class<?> pClass = callingContext.getBundle().loadClass(realName);
+                    providers.add(pClass.newInstance());
+                }
+            } catch (Exception ex) {
+                LOG.warn("Provider " + className.trim() + " can not be loaded or created " + ex.getMessage(), ex);
+            }
+        }
+        return providers;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/util/OsgiUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/util/OsgiUtils.java b/common/src/main/java/org/apache/cxf/dosgi/common/util/OsgiUtils.java
new file mode 100644
index 0000000..aa24903
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/util/OsgiUtils.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.cxf.dosgi.common.util;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class OsgiUtils {
+
+    public static final Logger LOG = LoggerFactory.getLogger(OsgiUtils.class);
+
+    private OsgiUtils() {
+    }
+
+    public static boolean getBooleanProperty(Map<String, Object> sd, String name) {
+        return toBoolean(sd.get(name));
+    }
+
+    public static boolean toBoolean(Object value) {
+        return value instanceof Boolean && (Boolean) value
+            || value instanceof String && Boolean.parseBoolean((String)value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Collection<String> getMultiValueProperty(Object property) {
+        if (property == null) {
+            return null;
+        } else if (property instanceof Collection) {
+            return (Collection<String>)property;
+        } else if (property instanceof String[]) {
+            return Arrays.asList((String[])property);
+        } else {
+            return Collections.singleton(property.toString());
+        }
+    }
+
+    public static String getProperty(EndpointDescription endpoint, String name) {
+        return getProperty(endpoint.getProperties(), name);
+    }
+
+    public static String getProperty(Map<String, Object> dict, String name) {
+        Object value = dict.get(name);
+        return value instanceof String ? (String) value : null;
+    }
+
+    public static String getFirstNonEmptyStringProperty(Map<String, Object> dict, String ... keys) {
+        for (String key : keys) {
+            String value = getProperty(dict, key);
+            if (value != null) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/util/ServerWrapper.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/util/ServerWrapper.java b/common/src/main/java/org/apache/cxf/dosgi/common/util/ServerWrapper.java
new file mode 100644
index 0000000..22144ca
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/util/ServerWrapper.java
@@ -0,0 +1,49 @@
+/**
+ * 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.cxf.dosgi.common.util;
+
+import java.io.IOException;
+
+import org.apache.aries.rsa.spi.Endpoint;
+import org.apache.cxf.endpoint.Server;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+
+public class ServerWrapper implements Endpoint {
+    private EndpointDescription desc;
+    private Server server;
+
+    public ServerWrapper(EndpointDescription desc, Server server) {
+        this.desc = desc;
+        this.server = server;
+    }
+    
+    public Server getServer() {
+        return this.server;
+    }
+
+    @Override
+    public void close() throws IOException {
+        this.server.destroy();
+    }
+
+    @Override
+    public EndpointDescription description() {
+        return this.desc;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/main/java/org/apache/cxf/dosgi/common/util/StringPlus.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/util/StringPlus.java b/common/src/main/java/org/apache/cxf/dosgi/common/util/StringPlus.java
new file mode 100644
index 0000000..c7123b2
--- /dev/null
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/util/StringPlus.java
@@ -0,0 +1,72 @@
+/**
+ * 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.cxf.dosgi.common.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class StringPlus {
+
+    private static final Logger LOG = LoggerFactory.getLogger(StringPlus.class);
+
+    private StringPlus() {
+        // never constructed
+    }
+
+    @SuppressWarnings("rawtypes")
+    public static String[] normalize(Object object) {
+        if (object instanceof String) {
+            String s = (String)object;
+            String[] values = s.split(",");
+            List<String> list = new ArrayList<String>();
+            for (String val : values) {
+                String actualValue = val.trim();
+                if (!actualValue.isEmpty()) {
+                    list.add(actualValue);
+                }
+            }
+            return list.toArray(new String[list.size()]);
+        }
+
+        if (object instanceof String[]) {
+            return (String[])object;
+        }
+        
+        if (object instanceof Collection) {
+            Collection col = (Collection)object;
+            List<String> ar = new ArrayList<String>(col.size());
+            for (Object o : col) {
+                if (o instanceof String) {
+                    String s = (String)o;
+                    ar.add(s);
+                } else {
+                    LOG.warn("stringPlus contained non string element in list! Element was skipped");
+                }
+            }
+            return ar.toArray(new String[ar.size()]);
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManagerTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManagerTest.java b/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManagerTest.java
new file mode 100644
index 0000000..c943f79
--- /dev/null
+++ b/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/HttpServiceManagerTest.java
@@ -0,0 +1,118 @@
+/**
+ * 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.cxf.dosgi.common.httpservice;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+
+import java.util.Dictionary;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+import org.junit.Assert;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+
+import junit.framework.TestCase;
+
+public class HttpServiceManagerTest extends TestCase {
+
+    public void testGetAbsoluteAddress() {
+        HttpServiceManager manager = new HttpServiceManager();
+        manager.initFromConfig(null);
+        String localIp = LocalHostUtil.getLocalIp();
+
+        String address1 = manager.getAbsoluteAddress(null, "/myservice");
+        assertEquals("http://" + localIp + ":8181/cxf/myservice", address1);
+
+        String address2 = manager.getAbsoluteAddress("/mycontext", "/myservice");
+        assertEquals("http://" + localIp + ":8181/mycontext/myservice", address2);
+    }
+
+    public void testRegisterAndUnregisterServlet() throws Exception {
+        IMocksControl c = EasyMock.createControl();
+        BundleContext dswContext = c.createMock(BundleContext.class);
+        Filter filter = c.createMock(Filter.class);
+        expect(dswContext.createFilter(EasyMock.eq("(service.id=12345)"))).andReturn(filter).once();
+        Capture<ServiceListener> captured = EasyMock.newCapture();
+        dswContext.addServiceListener(EasyMock.capture(captured), EasyMock.<String>anyObject());
+        expectLastCall().atLeastOnce();
+        expect(dswContext.getProperty("org.apache.cxf.httpservice.requirefilter")).andReturn(null).atLeastOnce();
+        ServletConfig config = c.createMock(ServletConfig.class);
+        expect(config.getInitParameter(EasyMock.<String>anyObject())).andReturn(null).atLeastOnce();
+        ServletContext servletContext = c.createMock(ServletContext.class);
+        expect(config.getServletContext()).andReturn(servletContext);
+        final HttpService httpService = new DummyHttpService(config);
+        ServiceReference<?> sr = c.createMock(ServiceReference.class);
+        expect(sr.getProperty(EasyMock.eq("service.id"))).andReturn(12345L).atLeastOnce();
+        expect(servletContext.getResourceAsStream((String)EasyMock.anyObject())).andReturn(null).anyTimes();
+        c.replay();
+
+        HttpServiceManager h = new HttpServiceManager();
+        h.setContext(dswContext);
+        h.setHttpService(httpService);
+        Bus bus = BusFactory.newInstance().createBus();
+        h.registerServlet(bus, "/myService", dswContext, 12345L);
+
+        ServiceEvent event = new ServiceEvent(ServiceEvent.UNREGISTERING, sr);
+        captured.getValue().serviceChanged(event);
+        c.verify();
+    }
+
+    static class DummyHttpService implements HttpService {
+
+        private ServletConfig config;
+
+        DummyHttpService(ServletConfig config) {
+            this.config = config;
+        }
+
+        @SuppressWarnings("rawtypes")
+        public void registerServlet(String alias, Servlet servlet, Dictionary initparams, HttpContext context)
+            throws ServletException, NamespaceException {
+            Assert.assertEquals("/myService", alias);
+            servlet.init(config);
+        }
+
+        public void registerResources(String alias, String name, HttpContext context) throws NamespaceException {
+            throw new RuntimeException("This method should not be called");
+        }
+
+        public void unregister(String alias) {
+        }
+
+        public HttpContext createDefaultHttpContext() {
+            return EasyMock.createNiceMock(HttpContext.class);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContextTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContextTest.java b/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContextTest.java
new file mode 100644
index 0000000..aac1204
--- /dev/null
+++ b/common/src/test/java/org/apache/cxf/dosgi/common/httpservice/SecurityDelegatingHttpContextTest.java
@@ -0,0 +1,267 @@
+/**
+ * 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.cxf.dosgi.common.httpservice;
+
+import java.io.PrintWriter;
+import java.net.URL;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings({
+    "unchecked", "rawtypes"
+   })
+public class SecurityDelegatingHttpContextTest extends TestCase {
+
+    protected HttpContext defaultHttpContext;
+    protected SecurityDelegatingHttpContext httpContext;
+    protected CommitResponseFilter commitFilter;
+    protected DoNothingFilter doNothingFilter;
+    protected AccessDeniedFilter accessDeniedFilter;
+    protected String mimeType;
+    protected URL url; // does not need to exist
+
+    public void setUp() throws Exception {
+        mimeType = "text/xml";
+        url = new URL("file:test.xml"); // does not need to exist
+
+        // Sample filters
+        commitFilter = new CommitResponseFilter();
+        doNothingFilter = new DoNothingFilter();
+        accessDeniedFilter = new AccessDeniedFilter();
+
+        // Mock up the default http context
+        defaultHttpContext = EasyMock.createNiceMock(HttpContext.class);
+        EasyMock.expect(defaultHttpContext.getMimeType((String)EasyMock.anyObject())).andReturn(mimeType);
+        EasyMock.expect(defaultHttpContext.getResource((String)EasyMock.anyObject())).andReturn(url);
+        EasyMock.replay(defaultHttpContext);
+    }
+
+    public void testFilterRequired() throws Exception {
+        // Mock up the service references
+        ServiceReference[] serviceReferences = new ServiceReference[] {};
+
+        // Mock up the bundle context
+        BundleContext bundleContext = EasyMock.createNiceMock(BundleContext.class);
+        EasyMock.expect(bundleContext.getServiceReferences(Filter.class.getName(),
+                                                           "(org.apache.cxf.httpservice.filter=true)"))
+            .andReturn(serviceReferences);
+        EasyMock.replay(bundleContext);
+
+        // Set up the secure http context
+        httpContext = new SecurityDelegatingHttpContext(bundleContext, defaultHttpContext);
+        httpContext.requireFilter = true;
+
+        // Ensure that the httpContext doesn't allow the request to be processed, since there are no registered servlet
+        // filters
+        HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+        EasyMock.replay(request);
+        HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+        EasyMock.replay(response);
+        boolean requestAllowed = httpContext.handleSecurity(request, response);
+        Assert.assertFalse(requestAllowed);
+
+        // Ensure that the httpContext returns true if there is no requirement for registered servlet filters
+        httpContext.requireFilter = false;
+        requestAllowed = httpContext.handleSecurity(request, response);
+        Assert.assertTrue(requestAllowed);
+    }
+
+    public void testSingleCommitFilter() throws Exception {
+        // Mock up the service references
+        ServiceReference filterReference = EasyMock.createNiceMock(ServiceReference.class);
+        EasyMock.replay(filterReference);
+        ServiceReference[] serviceReferences = new ServiceReference[] {
+            filterReference
+        };
+
+        // Mock up the bundle context
+        BundleContext bundleContext = EasyMock.createNiceMock(BundleContext.class);
+        EasyMock.expect(bundleContext.getServiceReferences((String)EasyMock.anyObject(), (String)EasyMock.anyObject()))
+            .andReturn(serviceReferences);
+        EasyMock.expect(bundleContext.getService((ServiceReference)EasyMock.anyObject())).andReturn(commitFilter);
+        EasyMock.replay(bundleContext);
+
+        // Set up the secure http context
+        httpContext = new SecurityDelegatingHttpContext(bundleContext, defaultHttpContext);
+
+        // Ensure that the httpContext returns false, since the filter has committed the response
+        HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+        EasyMock.replay(request);
+        HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+        EasyMock.expect(response.isCommitted()).andReturn(false); // the first call checks to see whether to invoke the
+                                                                  // filter
+        EasyMock.expect(response.isCommitted()).andReturn(true); // the second is called to determine the handleSecurity
+                                                                 // return value
+        EasyMock.expect(response.getWriter()).andReturn(new PrintWriter(System.out));
+        EasyMock.replay(response);
+        Assert.assertFalse(httpContext.handleSecurity(request, response));
+
+        // Ensure that the appropriate filters were called
+        Assert.assertTrue(commitFilter.called);
+        Assert.assertFalse(doNothingFilter.called);
+        Assert.assertFalse(accessDeniedFilter.called);
+    }
+
+    public void testFilterChain() throws Exception {
+        // Mock up the service references
+        ServiceReference filterReference = EasyMock.createNiceMock(ServiceReference.class);
+        EasyMock.replay(filterReference);
+        ServiceReference[] serviceReferences = new ServiceReference[] {
+            filterReference, filterReference
+        };
+
+        // Mock up the bundle context
+        BundleContext bundleContext = EasyMock.createNiceMock(BundleContext.class);
+        EasyMock.expect(bundleContext.getServiceReferences((String)EasyMock.anyObject(), (String)EasyMock.anyObject()))
+            .andReturn(serviceReferences);
+        EasyMock.expect(bundleContext.getService((ServiceReference)EasyMock.anyObject())).andReturn(doNothingFilter);
+        EasyMock.expect(bundleContext.getService((ServiceReference)EasyMock.anyObject())).andReturn(commitFilter);
+        EasyMock.replay(bundleContext);
+
+        // Set up the secure http context
+        httpContext = new SecurityDelegatingHttpContext(bundleContext, defaultHttpContext);
+
+        // Ensure that the httpContext returns false, since the filter has committed the response
+        HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+        EasyMock.replay(request);
+        HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+        EasyMock.expect(response.isCommitted()).andReturn(false); // doNothingFilter should not commit the response
+        EasyMock.expect(response.getWriter()).andReturn(new PrintWriter(System.out));
+        EasyMock.expect(response.isCommitted()).andReturn(false);
+        EasyMock.expect(response.isCommitted()).andReturn(true); // the commit filter indicating that it committed the
+                                                                 // response
+        EasyMock.replay(response);
+        Assert.assertFalse(httpContext.handleSecurity(request, response));
+
+        // Ensure that the appropriate filters were called
+        Assert.assertTrue(doNothingFilter.called);
+        Assert.assertTrue(commitFilter.called);
+        Assert.assertFalse(accessDeniedFilter.called);
+    }
+
+    public void testAllowRequest() throws Exception {
+        // Mock up the service references
+        ServiceReference filterReference = EasyMock.createNiceMock(ServiceReference.class);
+        EasyMock.replay(filterReference);
+        ServiceReference[] serviceReferences = new ServiceReference[] {
+            filterReference
+        };
+
+        // Mock up the bundle context
+        BundleContext bundleContext = EasyMock.createNiceMock(BundleContext.class);
+        EasyMock.expect(bundleContext.getServiceReferences((String)EasyMock.anyObject(), (String)EasyMock.anyObject()))
+            .andReturn(serviceReferences);
+        EasyMock.expect(bundleContext.getService((ServiceReference)EasyMock.anyObject())).andReturn(doNothingFilter);
+        EasyMock.replay(bundleContext);
+
+        // Set up the secure http context
+        httpContext = new SecurityDelegatingHttpContext(bundleContext, defaultHttpContext);
+
+        // Ensure that the httpContext returns true, since the filter has not committed the response
+        HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+        EasyMock.replay(request);
+        HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+        EasyMock.expect(response.isCommitted()).andReturn(false);
+        EasyMock.replay(response);
+        Assert.assertTrue(httpContext.handleSecurity(request, response));
+
+        // Ensure that the appropriate filters were called
+        Assert.assertTrue(doNothingFilter.called);
+        Assert.assertFalse(commitFilter.called);
+        Assert.assertFalse(accessDeniedFilter.called);
+    }
+
+    public void testDelegation() throws Exception {
+        BundleContext bundleContext = EasyMock.createNiceMock(BundleContext.class);
+        EasyMock.replay(bundleContext);
+
+        // Set up the secure http context
+        httpContext = new SecurityDelegatingHttpContext(bundleContext, defaultHttpContext);
+
+        // Ensure that it delegates non-security calls to the wrapped implementation (in this case, the mock)
+        Assert.assertEquals(mimeType, httpContext.getMimeType(""));
+        Assert.assertEquals(url, httpContext.getResource(""));
+    }
+}
+
+class CommitResponseFilter implements Filter {
+
+    boolean called;
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    public void destroy() {
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws java.io.IOException, javax.servlet.ServletException {
+        called = true;
+        response.getWriter().write("committing the response");
+    }
+}
+
+class DoNothingFilter implements Filter {
+
+    boolean called;
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    public void destroy() {
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws java.io.IOException, javax.servlet.ServletException {
+        called = true;
+        chain.doFilter(request, response);
+    }
+}
+
+class AccessDeniedFilter implements Filter {
+
+    boolean called;
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    public void destroy() {
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws java.io.IOException, javax.servlet.ServletException {
+        called = true;
+        ((HttpServletResponse)response).sendError(HttpServletResponse.SC_FORBIDDEN);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/d2a3c75f/common/src/test/java/org/apache/cxf/dosgi/common/qos/IntentManagerImplTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/cxf/dosgi/common/qos/IntentManagerImplTest.java b/common/src/test/java/org/apache/cxf/dosgi/common/qos/IntentManagerImplTest.java
new file mode 100644
index 0000000..63a2fef
--- /dev/null
+++ b/common/src/test/java/org/apache/cxf/dosgi/common/qos/IntentManagerImplTest.java
@@ -0,0 +1,282 @@
+/**
+ * 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.cxf.dosgi.common.qos;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.aries.rsa.spi.IntentUnsatisfiedException;
+import org.apache.cxf.binding.BindingConfiguration;
+import org.apache.cxf.dosgi.common.intent.DefaultIntentMapFactory;
+import org.apache.cxf.dosgi.common.intent.IntentManager;
+import org.apache.cxf.dosgi.common.intent.IntentManagerImpl;
+import org.apache.cxf.dosgi.common.intent.IntentMap;
+import org.apache.cxf.endpoint.AbstractEndpointFactory;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.feature.Feature;
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class IntentManagerImplTest extends Assert {
+
+    @Test
+    public void testIntents() throws Exception {
+        Map<String, Object> intents = new HashMap<String, Object>();
+        intents.put("A", new TestFeature("A"));
+        intents.put("SOAP", new TestFeature("SOAP"));
+        final IntentMap intentMap = new IntentMap(intents);
+
+        IMocksControl control = EasyMock.createNiceControl();
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+
+        IntentManager intentManager = new IntentManagerImpl(intentMap, 10000);
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", "A");
+
+        List<String> effectiveIntents = Arrays.asList(intentManager.applyIntents(features, factory, props));
+        assertEquals(Arrays.asList("A", "SOAP"), effectiveIntents);
+    }
+
+    @Test
+    public void testMultiIntents() {
+        final IntentMap intentMap = new IntentMap(new DefaultIntentMapFactory().create());
+        intentMap.put("confidentiality.message", new TestFeature("confidentiality.message"));
+        intentMap.put("transactionality", new TestFeature("transactionality"));
+
+        IMocksControl control = EasyMock.createNiceControl();
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+
+        IntentManager intentManager = new IntentManagerImpl(intentMap);
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", "transactionality confidentiality.message");
+
+        List<String> effectiveIntents = Arrays.asList(intentManager.applyIntents(features, factory, props));
+        assertTrue(effectiveIntents.contains("transactionality"));
+        assertTrue(effectiveIntents.contains("confidentiality.message"));
+    }
+
+    @Test
+    public void testFailedIntent() {
+        Map<String, Object> intents = new HashMap<String, Object>();
+        intents.put("A", new TestFeature("A"));
+        final IntentMap intentMap = new IntentMap(intents);
+
+        IMocksControl control = EasyMock.createNiceControl();
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+
+        IntentManager intentManager = new IntentManagerImpl(intentMap);
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", "A B");
+        // ServiceEndpointDescription sd =
+        //         new ServiceEndpointDescriptionImpl(Arrays.asList(String.class.getName()), props);
+
+        try {
+            intentManager.applyIntents(features, factory, props);
+            Assert.fail("applyIntents() should have thrown an exception as there was an unsatisfiable intent");
+        } catch (IntentUnsatisfiedException iue) {
+            assertEquals("B", iue.getIntent());
+        }
+    }
+
+    @Test
+    public void testInferIntents() {
+        Map<String, Object> intents = new HashMap<String, Object>();
+        intents.put("SOAP", new TestFeature("SOAP"));
+        intents.put("Prov", "PROVIDED");
+        AbstractFeature feat1 = new TestFeature("feat1");
+        intents.put("A", feat1);
+        intents.put("A_alt", feat1);
+        intents.put("B", new TestFeature("B"));
+        final IntentMap intentMap = new IntentMap(intents);
+
+        IMocksControl control = EasyMock.createNiceControl();
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+
+        IntentManager intentManager = new IntentManagerImpl(intentMap);
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", "A");
+        // ServiceEndpointDescription sd =
+        //         new ServiceEndpointDescriptionImpl(Arrays.asList(String.class.getName()), props);
+
+        List<String> effectiveIntents = Arrays.asList(intentManager.applyIntents(features, factory, props));
+        assertEquals(4, effectiveIntents.size());
+        assertTrue(effectiveIntents.contains("Prov"));
+        assertTrue(effectiveIntents.contains("A"));
+        assertTrue(effectiveIntents.contains("A_alt"));
+    }
+
+    @Test
+    public void testDefaultBindingIntent() {
+        IMocksControl control = EasyMock.createNiceControl();
+
+        Map<String, Object> intents = new HashMap<String, Object>();
+        BindingConfiguration feat1 = control.createMock(BindingConfiguration.class);
+        intents.put("A", new AbstractFeature() {
+        });
+        intents.put("SOAP", feat1);
+        intents.put("SOAP.1_1", feat1);
+        intents.put("SOAP.1_2", control.createMock(BindingConfiguration.class));
+        final IntentMap intentMap = new IntentMap(intents);
+
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+        IntentManager intentManager = new IntentManagerImpl(intentMap);
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", "A");
+        // ServiceEndpointDescription sd =
+        //         new ServiceEndpointDescriptionImpl(Arrays.asList(String.class.getName()), props);
+
+        List<String> effectiveIntents = Arrays.asList(intentManager.applyIntents(features, factory, props));
+        assertEquals(3, effectiveIntents.size());
+        assertTrue(effectiveIntents.contains("A"));
+        assertTrue(effectiveIntents.contains("SOAP"));
+        assertTrue(effectiveIntents.contains("SOAP.1_1"));
+    }
+
+    @Test
+    public void testExplicitBindingIntent() {
+        IMocksControl control = EasyMock.createNiceControl();
+
+        Map<String, Object> intents = new HashMap<String, Object>();
+        BindingConfiguration feat1 = control.createMock(BindingConfiguration.class);
+        intents.put("A", new AbstractFeature() {
+        });
+        intents.put("SOAP", feat1);
+        intents.put("SOAP.1_1", feat1);
+        intents.put("SOAP.1_2", control.createMock(BindingConfiguration.class));
+        final IntentMap intentMap = new IntentMap(intents);
+
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+
+        IntentManager intentManager = new IntentManagerImpl(intentMap);
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", "A SOAP.1_2");
+        // ServiceEndpointDescription sd =
+        //         new ServiceEndpointDescriptionImpl(Arrays.asList(String.class.getName()), props);
+
+        List<String> effectiveIntents = Arrays.asList(intentManager.applyIntents(features, factory, props));
+        assertEquals(2, effectiveIntents.size());
+        assertTrue(effectiveIntents.contains("A"));
+        assertTrue(effectiveIntents.contains("SOAP.1_2"));
+    }
+
+    public void testInheritMasterIntentMapDefault() {
+        List<String> features = runTestInheritMasterIntentMap("A B");
+
+        assertEquals(2, features.size());
+        assertTrue(features.contains("appFeatureA"));
+        assertTrue(features.contains("masterFeatureB"));
+    }
+
+    public void testInheritMasterIntentMap() {
+        List<String> features = runTestInheritMasterIntentMap("A B");
+
+        assertEquals(2, features.size());
+        assertTrue(features.contains("appFeatureA"));
+        assertTrue(features.contains("masterFeatureB"));
+    }
+
+    private List<String> runTestInheritMasterIntentMap(String requestedIntents) {
+        Map<String, Object> masterIntents = new HashMap<String, Object>();
+        masterIntents.put("A", new TestFeature("masterFeatureA"));
+        masterIntents.put("B", new TestFeature("masterFeatureB"));
+        final IntentMap intentMap = new IntentMap(masterIntents);
+        intentMap.put("A", new TestFeature("appFeatureA"));
+
+        IMocksControl control = EasyMock.createNiceControl();
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", requestedIntents);
+
+        IntentManagerImpl intentManager = new IntentManagerImpl(intentMap);
+        intentManager.applyIntents(features, factory, props);
+
+        List<String> featureNames = new ArrayList<String>();
+        for (Feature f : features) {
+            featureNames.add(f.toString());
+        }
+        return featureNames;
+    }
+
+    @Test
+    public void testProvidedIntents() {
+        Map<String, Object> masterIntents = new HashMap<String, Object>();
+        masterIntents.put("SOAP", "SOAP");
+        masterIntents.put("A", "Provided");
+        masterIntents.put("B", "PROVIDED");
+        final IntentMap intentMap = new IntentMap(masterIntents);
+
+        IMocksControl control = EasyMock.createNiceControl();
+        List<Feature> features = new ArrayList<Feature>();
+        AbstractEndpointFactory factory = control.createMock(AbstractEndpointFactory.class);
+        control.replay();
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("osgi.remote.requires.intents", "B A");
+
+        IntentManager intentManager = new IntentManagerImpl(intentMap);
+
+        Set<String> effectiveIntents = new HashSet<String>(Arrays.asList(intentManager.applyIntents(features,
+                                                                                                    factory,
+                                                                                                    props)));
+        Set<String> expectedIntents = new HashSet<String>(Arrays.asList(new String[] {"A", "B", "SOAP"}));
+        assertEquals(expectedIntents, effectiveIntents);
+    }
+
+    private static final class TestFeature extends AbstractFeature {
+
+        private final String name;
+
+        private TestFeature(String n) {
+            name = n;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+}


Mime
View raw message