cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cschnei...@apache.org
Subject [14/15] cxf-dosgi git commit: [DOSGI-232] Remove code that moved to Aries-rsa and refer to it instead
Date Fri, 11 Mar 2016 22:54:01 GMT
http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/HttpServiceManager.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/HttpServiceManager.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/HttpServiceManager.java
new file mode 100644
index 0000000..eca5460
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/HttpServiceManager.java
@@ -0,0 +1,176 @@
+/**
+ * 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.dsw.handlers;
+
+import java.util.Collections;
+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.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HttpServiceManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpServiceManager.class);
+    private static final long SERVICE_LOOKUP_TIMEOUT = 10000;
+    private ServiceTracker<HttpService, HttpService> tracker;
+    private BundleContext bundleContext;
+    private Map<Long, String> exportedAliases = Collections.synchronizedMap(new HashMap<Long, String>());
+    private String httpBase;
+    private String cxfServletAlias;
+
+    public HttpServiceManager(BundleContext bundleContext, String httpBase, String cxfServletAlias) {
+        this(bundleContext, httpBase, cxfServletAlias,
+             new ServiceTracker<HttpService, HttpService>(bundleContext, HttpService.class, null));
+        this.tracker.open();
+    }
+
+    // Only for tests
+    public HttpServiceManager(BundleContext bundleContext,
+                              String httpBase, String cxfServletAlias,
+                              ServiceTracker<HttpService, HttpService> tracker) {
+        this.bundleContext = bundleContext;
+        this.tracker = tracker;
+        this.httpBase = getWithDefault(httpBase, "http://" + LocalHostUtil.getLocalIp() + ":8181");
+        this.cxfServletAlias = getWithDefault(cxfServletAlias, "/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 {
+            HttpService httpService = getHttpService();
+            httpService.registerServlet(contextRoot, cxf, new Hashtable<String, String>(),
+                                       getHttpContext(callingContext, httpService));
+
+            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;
+    }
+
+    protected HttpService getHttpService() {
+        HttpService service = null;
+        try {
+            service = tracker.waitForService(SERVICE_LOOKUP_TIMEOUT);
+        } catch (InterruptedException ex) {
+            LOG.warn("waitForService interrupeted", ex);
+        }
+        if (service == null) {
+            throw new RuntimeException("No HTTPService found");
+        }
+        return service;
+    }
+
+    private HttpContext getHttpContext(BundleContext bc, HttpService httpService) {
+        HttpContext httpContext = httpService.createDefaultHttpContext();
+        return new SecurityDelegatingHttpContext(bc, httpContext);
+    }
+
+    /**
+     * 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 = bundleContext.createFilter("(" + org.osgi.framework.Constants.SERVICE_ID + "=" + sid + ")");
+            if (f != null) {
+                bundleContext.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);
+        }
+    }
+
+    protected String getDefaultAddress(Class<?> type) {
+        return "/" + type.getName().replace('.', '/');
+    }
+
+    protected String getAbsoluteAddress(String contextRoot, String relativeEndpointAddress) {
+        if (relativeEndpointAddress.startsWith("http")) {
+            return relativeEndpointAddress;
+        }
+        String effContextRoot = contextRoot == null ? cxfServletAlias : contextRoot;
+        return this.httpBase + effContextRoot + relativeEndpointAddress;
+    }
+
+    public void close() {
+        tracker.close();
+    }
+
+    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 http = getHttpService();
+                http.unregister(alias);
+            } catch (Exception e) {
+                LOG.warn("An exception occurred while unregistering service for HTTP servlet alias '{}'", alias, e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSPojoConfigurationTypeHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSPojoConfigurationTypeHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSPojoConfigurationTypeHandler.java
new file mode 100644
index 0000000..8f4f152
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSPojoConfigurationTypeHandler.java
@@ -0,0 +1,201 @@
+/**
+ * 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.dsw.handlers;
+
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.aries.rsa.spi.Endpoint;
+import org.apache.aries.rsa.spi.IntentUnsatisfiedException;
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.util.ProxyClassLoader;
+import org.apache.cxf.dosgi.dsw.Constants;
+import org.apache.cxf.dosgi.dsw.qos.IntentManager;
+import org.apache.cxf.dosgi.dsw.util.OsgiUtils;
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.client.Client;
+import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.model.UserResource;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JaxRSPojoConfigurationTypeHandler extends AbstractPojoConfigurationTypeHandler {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JaxRSPojoConfigurationTypeHandler.class);
+
+    public JaxRSPojoConfigurationTypeHandler(BundleContext dswBC,
+                                             IntentManager intentManager,
+                                             HttpServiceManager httpServiceManager) {
+        super(dswBC, intentManager, httpServiceManager);
+    }
+
+    public String[] getSupportedTypes() {
+        return new String[] {Constants.RS_CONFIG_TYPE};
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Object importEndpoint(ClassLoader consumerLoader,
+                                 BundleContext consumerContext,
+                                 Class[] interfaces,
+                                 EndpointDescription endpoint) {
+        Class<?> iClass = interfaces[0];
+        String address = getPojoAddress(endpoint, iClass);
+        if (address == null) {
+            LOG.warn("Remote address is unavailable");
+            return null;
+        }
+        ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+        try {
+            return createJaxrsProxy(address, consumerContext, iClass, null, endpoint);
+        } catch (Throwable e) {
+            Thread.currentThread().setContextClassLoader(oldClassLoader);
+        }
+
+        try {
+            ProxyClassLoader cl = new ProxyClassLoader(iClass.getClassLoader());
+            cl.addLoader(Client.class.getClassLoader());
+            return createJaxrsProxy(address, consumerContext, iClass, cl, endpoint);
+        } catch (Throwable e) {
+            LOG.warn("proxy creation failed", e);
+        }
+
+        return null;
+    }
+
+    protected Object createJaxrsProxy(String address,
+                                      BundleContext callingContext,
+                                      Class<?> iClass,
+                                      ClassLoader loader,
+                                      EndpointDescription endpoint) {
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        bean.setAddress(address);
+        if (loader != null) {
+            bean.setClassLoader(loader);
+        }
+
+        addRsInterceptorsFeaturesProps(bean, callingContext, endpoint.getProperties());
+
+        List<UserResource> resources = JaxRSUtils.getModel(callingContext, iClass);
+        if (resources != null) {
+            bean.setModelBeansWithServiceClass(resources, iClass);
+        } else {
+            bean.setServiceClass(iClass);
+        }
+        List<Object> providers = JaxRSUtils.getProviders(callingContext, endpoint.getProperties());
+        if (providers != null && !providers.isEmpty()) {
+            bean.setProviders(providers);
+        }
+        Thread.currentThread().setContextClassLoader(JAXRSClientFactoryBean.class.getClassLoader());
+        return getProxy(bean.create(), iClass);
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Endpoint exportService(Object serviceBean,
+                                  BundleContext callingContext,
+                                  Map<String, Object> endpointProps,
+                                  Class[] exportedInterfaces) throws IntentUnsatisfiedException {
+        String contextRoot = getServletContextRoot(endpointProps);
+        String address;
+        Class<?> iClass = exportedInterfaces[0];
+        if (contextRoot == null) {
+            address = getServerAddress(endpointProps, iClass);
+        } else {
+            address = getClientAddress(endpointProps);
+            if (address == null) {
+                address = "/";
+            }
+        }
+        final Long sid = (Long) endpointProps.get(RemoteConstants.ENDPOINT_SERVICE_ID);
+        Bus bus = createBus(sid, callingContext, contextRoot);
+
+        LOG.info("Creating a " + iClass.getName()
+                 + " endpoint via JaxRSPojoConfigurationTypeHandler, address is " + address);
+
+        JAXRSServerFactoryBean factory = createServerFactory(callingContext, endpointProps, 
+                                                             iClass, serviceBean, address, bus);
+        String completeEndpointAddress = httpServiceManager.getAbsoluteAddress(contextRoot, address);
+
+        EndpointDescription epd = createEndpointDesc(endpointProps, new String[] {Constants.RS_CONFIG_TYPE},
+                completeEndpointAddress, new String[] {"HTTP"});
+
+        return createServerFromFactory(factory, epd);
+    }
+
+    private Endpoint createServerFromFactory(JAXRSServerFactoryBean factory,
+                                                       EndpointDescription epd) {
+        ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(JAXRSServerFactoryBean.class.getClassLoader());
+            Server server = factory.create();
+            return new ServerWrapper(epd, server);
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldClassLoader);
+        }
+    }
+
+    private JAXRSServerFactoryBean createServerFactory(BundleContext callingContext,
+                                                       Map<String, Object> sd,
+                                                       Class<?> iClass,
+                                                       Object serviceBean,
+                                                       String address,
+                                                       Bus bus) {
+        JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
+        factory.setBus(bus);
+        List<UserResource> resources = JaxRSUtils.getModel(callingContext, iClass);
+        if (resources != null) {
+            factory.setModelBeansWithServiceClass(resources, iClass);
+            factory.setServiceBeanObjects(serviceBean);
+        } else {
+            factory.setServiceClass(iClass);
+            factory.setResourceProvider(iClass, new SingletonResourceProvider(serviceBean));
+        }
+        factory.setAddress(address);
+        List<Object> providers = JaxRSUtils.getProviders(callingContext, sd);
+        if (providers != null && !providers.isEmpty()) {
+            factory.setProviders(providers);
+        }
+        addRsInterceptorsFeaturesProps(factory, callingContext, sd);
+        String location = OsgiUtils.getProperty(sd, Constants.RS_WADL_LOCATION);
+        if (location != null) {
+            URL wadlURL = callingContext.getBundle().getResource(location);
+            if (wadlURL != null) {
+                factory.setDocLocation(wadlURL.toString());
+            }
+        }
+        return factory;
+    }
+
+    protected String getPojoAddress(EndpointDescription endpoint, Class<?> iClass) {
+        String address = OsgiUtils.getProperty(endpoint, Constants.RS_ADDRESS_PROPERTY);
+
+        if (address == null) {
+            address = httpServiceManager.getDefaultAddress(iClass);
+            if (address != null) {
+                LOG.info("Using a default address: " + address);
+            }
+        }
+        return address;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSUtils.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSUtils.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSUtils.java
new file mode 100644
index 0000000..6e78744
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/JaxRSUtils.java
@@ -0,0 +1,121 @@
+/**
+ * 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.dsw.handlers;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.dosgi.dsw.util.OsgiUtils;
+import org.apache.cxf.jaxrs.model.UserResource;
+import org.apache.cxf.jaxrs.provider.aegis.AegisElementProvider;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class JaxRSUtils {
+
+    public static final String MODEL_FOLDER = "/OSGI-INF/cxf/jaxrs/";
+    public static final String DEFAULT_MODEL = "/OSGI-INF/cxf/jaxrs/model.xml";
+    public static final String PROVIDERS_FILTER = "(|"
+            + "(objectClass=javax.ws.rs.ext.MessageBodyReader)"
+            + "(objectClass=javax.ws.rs.ext.MessageBodyWriter)"
+            + "(objectClass=javax.ws.rs.ext.ExceptionMapper)"
+            + "(objectClass=org.apache.cxf.jaxrs.ext.RequestHandler)"
+            + "(objectClass=org.apache.cxf.jaxrs.ext.ResponseHandler)"
+            + "(objectClass=org.apache.cxf.jaxrs.ext.ParameterHandler)"
+            + "(objectClass=org.apache.cxf.jaxrs.ext.ResponseExceptionMapper)"
+            + ")";
+    private static final Logger LOG = LoggerFactory.getLogger(JaxRSUtils.class);
+
+    private JaxRSUtils() {
+        // never constructed
+    }
+
+    @SuppressWarnings({
+     "rawtypes", "unchecked"
+    })
+    static List<Object> getProviders(BundleContext callingContext, Map<String, Object> sd) {
+        List<Object> providers = new ArrayList<Object>();
+        if ("aegis".equals(sd.get(org.apache.cxf.dosgi.dsw.Constants.RS_DATABINDING_PROP_KEY))) {
+            providers.add(new AegisElementProvider());
+        }
+
+        providers.addAll(ClassUtils.loadProviderClasses(callingContext,
+                                                        sd,
+                                                        org.apache.cxf.dosgi.dsw.Constants.RS_PROVIDER_PROP_KEY));
+
+        Object globalQueryProp = sd.get(org.apache.cxf.dosgi.dsw.Constants.RS_PROVIDER_GLOBAL_PROP_KEY);
+        boolean globalQueryRequired = globalQueryProp == null || OsgiUtils.toBoolean(globalQueryProp);
+        if (!globalQueryRequired) {
+            return providers;
+        }
+
+        boolean cxfProvidersOnly = OsgiUtils.getBooleanProperty(sd,
+                org.apache.cxf.dosgi.dsw.Constants.RS_PROVIDER_EXPECTED_PROP_KEY);
+
+        try {
+            ServiceReference[] refs = callingContext.getServiceReferences((String)null, PROVIDERS_FILTER);
+            if (refs != null) {
+                for (ServiceReference ref : refs) {
+                    if (!cxfProvidersOnly
+                        || OsgiUtils.toBoolean(ref
+                            .getProperty(org.apache.cxf.dosgi.dsw.Constants.RS_PROVIDER_PROP_KEY))) {
+                        providers.add(callingContext.getService(ref));
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            LOG.debug("Problems finding JAXRS providers " + ex.getMessage(), ex);
+        }
+        return providers;
+    }
+
+    static List<UserResource> getModel(BundleContext callingContext, Class<?> iClass) {
+        String classModel = MODEL_FOLDER + iClass.getSimpleName() + "-model.xml";
+        List<UserResource> list = getModel(callingContext, iClass, classModel);
+        return list != null ? list : getModel(callingContext, iClass, DEFAULT_MODEL);
+    }
+
+    private static List<UserResource> getModel(BundleContext callingContext, Class<?> iClass, String name) {
+        InputStream r = iClass.getClassLoader().getResourceAsStream(name);
+        if (r == null) {
+            URL u = callingContext.getBundle().getResource(name);
+            if (u != null) {
+                try {
+                    r = u.openStream();
+                } catch (Exception ex) {
+                    LOG.info("Problems opening a user model resource at " + u.toString());
+                }
+            }
+        }
+        if (r != null) {
+            try {
+                return ResourceUtils.getUserResources(r);
+            } catch (Exception ex) {
+                LOG.info("Problems reading a user model, it will be ignored");
+            }
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/LocalHostUtil.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/LocalHostUtil.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/LocalHostUtil.java
new file mode 100644
index 0000000..50e2127
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/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.dsw.handlers;
+
+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.
+ */
+public 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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/PojoConfigurationTypeHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/PojoConfigurationTypeHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/PojoConfigurationTypeHandler.java
new file mode 100644
index 0000000..bf92141
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/PojoConfigurationTypeHandler.java
@@ -0,0 +1,172 @@
+/**
+ * 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.dsw.handlers;
+
+import java.util.Map;
+
+import javax.jws.WebService;
+
+import org.apache.aries.rsa.spi.Endpoint;
+import org.apache.aries.rsa.spi.IntentUnsatisfiedException;
+import org.apache.cxf.Bus;
+import org.apache.cxf.aegis.databinding.AegisDatabinding;
+import org.apache.cxf.databinding.DataBinding;
+import org.apache.cxf.dosgi.dsw.Constants;
+import org.apache.cxf.dosgi.dsw.qos.IntentManager;
+import org.apache.cxf.frontend.ClientProxyFactoryBean;
+import org.apache.cxf.frontend.ServerFactoryBean;
+import org.apache.cxf.jaxb.JAXBDataBinding;
+import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
+import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PojoConfigurationTypeHandler extends AbstractPojoConfigurationTypeHandler {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PojoConfigurationTypeHandler.class);
+
+    public PojoConfigurationTypeHandler(BundleContext dswBC,
+                                        IntentManager intentManager,
+                                        HttpServiceManager httpServiceManager) {
+        super(dswBC, intentManager, httpServiceManager);
+    }
+
+    public String[] getSupportedTypes() {
+        return new String[] {Constants.WS_CONFIG_TYPE, Constants.WS_CONFIG_TYPE_OLD};
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Object importEndpoint(ClassLoader consumerLoader,
+                                 BundleContext consumerContext,
+                                 Class[] interfaces,
+                                 EndpointDescription endpoint) throws IntentUnsatisfiedException {
+        Class<?> iClass = interfaces[0];
+        Map<String, Object> sd = endpoint.getProperties();
+        String address = getClientAddress(sd);
+        if (address == null) {
+            LOG.warn("Remote address is unavailable");
+            // TODO: fire Event
+            return null;
+        }
+
+        LOG.info("Creating a " + iClass.getName() + " client, endpoint address is " + address);
+
+        ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+        try {
+            ClientProxyFactoryBean factory = createClientProxyFactoryBean(sd, iClass);
+            factory.getServiceFactory().setDataBinding(getDataBinding(sd, iClass));
+            factory.setServiceClass(iClass);
+            factory.setAddress(address);
+            addWsInterceptorsFeaturesProps(factory.getClientFactoryBean(), consumerContext, sd);
+            setClientWsdlProperties(factory.getClientFactoryBean(), bundleContext, sd, false);
+
+            intentManager.applyIntents(factory.getFeatures(), factory.getClientFactoryBean(), sd);
+
+            Thread.currentThread().setContextClassLoader(ClientProxyFactoryBean.class.getClassLoader());
+            return getProxy(factory.create(), iClass);
+        } catch (Exception e) {
+            LOG.warn("proxy creation failed", e);
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldClassLoader);
+        }
+        return null;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Endpoint exportService(Object serviceO,
+                                  BundleContext serviceContext,
+                                  Map<String, Object> endpointProps,
+                                  Class[] exportedInterfaces) throws IntentUnsatisfiedException {
+        Class<?> iClass = exportedInterfaces[0];
+        String address = getPojoAddress(endpointProps, iClass);
+        ServerFactoryBean factory = createServerFactoryBean(endpointProps, iClass);
+        factory.setDataBinding(getDataBinding(endpointProps, iClass));
+        String contextRoot = getServletContextRoot(endpointProps);
+
+        final Long sid = (Long) endpointProps.get(RemoteConstants.ENDPOINT_SERVICE_ID);
+        Bus bus = createBus(sid, serviceContext, contextRoot);
+        factory.setBus(bus);
+        factory.setServiceClass(iClass);
+        factory.setAddress(address);
+        
+        factory.setServiceBean(serviceO);
+        addWsInterceptorsFeaturesProps(factory, serviceContext, endpointProps);
+        setWsdlProperties(factory, serviceContext, endpointProps, false);
+        String[] intents = intentManager.applyIntents(factory.getFeatures(), factory, endpointProps);
+
+        String completeEndpointAddress = httpServiceManager.getAbsoluteAddress(contextRoot, address);
+        EndpointDescription epd = createEndpointDesc(endpointProps,
+                                                     new String[]{Constants.WS_CONFIG_TYPE},
+                                                     completeEndpointAddress, intents);
+        return createServerFromFactory(factory, epd);
+    }
+
+    private String getPojoAddress(Map<String, Object> sd, Class<?> iClass) {
+        String address = getClientAddress(sd);
+        if (address != null) {
+            return address;
+        }
+
+        // If the property is not of type string this will cause an ClassCastException which
+        // will be propagated to the ExportRegistration exception property.
+        Object port = sd.get(Constants.WS_PORT_PROPERTY);
+        if (port == null) {
+            port = "9000";
+        }
+
+        address = "http://localhost:" + port + "/" + iClass.getName().replace('.', '/');
+        LOG.info("Using a default address: " + address);
+        return address;
+    }
+
+    private DataBinding getDataBinding(Map<String, Object> sd, Class<?> iClass) {
+        Object dataBindingBeanProp = sd.get(Constants.WS_DATABINDING_BEAN_PROP_KEY);
+        if (dataBindingBeanProp instanceof DataBinding) {
+            return (DataBinding)dataBindingBeanProp;
+        } 
+        return isJAXB(sd, iClass) ? new JAXBDataBinding() : new AegisDatabinding();
+    }
+
+    private boolean isJAXB(Map<String, Object> sd, Class<?> iClass) {
+        String dataBindingName = (String)sd.get(Constants.WS_DATABINDING_PROP_KEY);
+        return (iClass.getAnnotation(WebService.class) != null
+            || Constants.WS_DATA_BINDING_JAXB.equals(dataBindingName))
+            && !Constants.WS_DATA_BINDING_AEGIS.equals(dataBindingName);
+    }
+
+    // Isolated so that it can be substituted for testing
+    protected ClientProxyFactoryBean createClientProxyFactoryBean(Map<String, Object> sd, Class<?> iClass) {
+        return isJAXWS(sd, iClass) ? new JaxWsProxyFactoryBean() : new ClientProxyFactoryBean();
+    }
+
+    // Isolated so that it can be substituted for testing
+    protected ServerFactoryBean createServerFactoryBean(Map<String, Object> sd, Class<?> iClass) {
+        return isJAXWS(sd, iClass) ? new JaxWsServerFactoryBean() : new ServerFactoryBean();
+    }
+
+    private boolean isJAXWS(Map<String, Object> sd, Class<?> iClass) {
+        String frontEnd = (String)sd.get(Constants.WS_FRONTEND_PROP_KEY);
+        return (iClass.getAnnotation(WebService.class) != null
+            || Constants.WS_FRONTEND_JAXWS.equals(frontEnd))
+            && !Constants.WS_FRONTEND_SIMPLE.equals(frontEnd);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/SecurityDelegatingHttpContext.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/SecurityDelegatingHttpContext.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/SecurityDelegatingHttpContext.java
new file mode 100644
index 0000000..7e9710b
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/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.dsw.handlers;
+
+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>
+ */
+public 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;
+
+    public 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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServerWrapper.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServerWrapper.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServerWrapper.java
new file mode 100644
index 0000000..bcc4963
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/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.dsw.handlers;
+
+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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java
new file mode 100644
index 0000000..6171a53
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java
@@ -0,0 +1,100 @@
+/**
+ * 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.dsw.handlers;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.ServiceException;
+
+public class ServiceInvocationHandler implements InvocationHandler {
+
+    private static final String REMOTE_EXCEPTION_TYPE = "REMOTE";
+    private static final Collection<Method> OBJECT_METHODS = Arrays.asList(Object.class.getMethods());
+
+    private Map<Method, List<Class<?>>> exceptionsMap = new HashMap<Method, List<Class<?>>>();
+    private Object serviceObject;
+
+    public ServiceInvocationHandler(Object serviceObject, Class<?> iType) {
+        this.serviceObject = serviceObject;
+        introspectType(iType);
+    }
+
+    public Object invoke(Object proxy, final Method m, Object[] params) throws Throwable {
+        if (OBJECT_METHODS.contains(m)) {
+            if (m.getName().equals("equals")) {
+                params = new Object[] {Proxy.getInvocationHandler(params[0])};
+            }
+            return m.invoke(this, params);
+        }
+
+        ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+            final Object[] paramsFinal = params;
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                public Object run() throws Exception {
+                    return m.invoke(serviceObject, paramsFinal);
+                }
+            });
+        } catch (Throwable ex) {
+            Throwable theCause = ex.getCause() == null ? ex : ex.getCause();
+            Throwable theCauseCause = theCause.getCause() == null ? theCause : theCause.getCause();
+            List<Class<?>> excTypes = exceptionsMap.get(m);
+            if (excTypes != null) {
+                for (Class<?> type : excTypes) {
+                    if (type.isAssignableFrom(theCause.getClass())) {
+                        throw theCause;
+                    }
+                    if (type.isAssignableFrom(theCauseCause.getClass())) {
+                        throw theCauseCause;
+                    }
+                }
+            }
+
+            throw new ServiceException(REMOTE_EXCEPTION_TYPE, theCause);
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldCl);
+        }
+    }
+
+    private void introspectType(Class<?> iType) {
+        for (Method m : iType.getDeclaredMethods()) {
+            for (Class<?> excType : m.getExceptionTypes()) {
+                if (Exception.class.isAssignableFrom(excType)) {
+                    List<Class<?>> types = exceptionsMap.get(m);
+                    if (types == null) {
+                        types = new ArrayList<Class<?>>();
+                        exceptionsMap.put(m, types);
+                    }
+                    types.add(excType);
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/WsdlConfigurationTypeHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/WsdlConfigurationTypeHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/WsdlConfigurationTypeHandler.java
new file mode 100644
index 0000000..5bf16d7
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/WsdlConfigurationTypeHandler.java
@@ -0,0 +1,160 @@
+/**
+ * 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.dsw.handlers;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+
+import org.apache.aries.rsa.spi.Endpoint;
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.databinding.DataBinding;
+import org.apache.cxf.dosgi.dsw.Constants;
+import org.apache.cxf.dosgi.dsw.qos.IntentManager;
+import org.apache.cxf.dosgi.dsw.util.OsgiUtils;
+import org.apache.cxf.jaxb.JAXBDataBinding;
+import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WsdlConfigurationTypeHandler extends AbstractPojoConfigurationTypeHandler {
+
+    private static final Logger LOG = LoggerFactory.getLogger(WsdlConfigurationTypeHandler.class);
+
+    public WsdlConfigurationTypeHandler(BundleContext dswBC,
+                                        IntentManager intentManager,
+                                        HttpServiceManager httpServiceManager) {
+        super(dswBC, intentManager, httpServiceManager);
+    }
+
+    public String[] getSupportedTypes() {
+        return new String[] {Constants.WSDL_CONFIG_TYPE};
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Object importEndpoint(ClassLoader consumerLoader,
+                                 BundleContext consumerContext,
+                                 Class[] interfaces,
+                                 EndpointDescription endpoint) {
+        Class<?> iClass = interfaces[0];
+        String wsdlAddressProp = getWsdlAddress(endpoint, iClass);
+        if (wsdlAddressProp == null) {
+            LOG.warn("WSDL address is unavailable");
+            return null;
+        }
+
+        URL wsdlAddress;
+        try {
+            wsdlAddress = new URL(wsdlAddressProp);
+        } catch (MalformedURLException ex) {
+            LOG.warn("WSDL address is malformed");
+            return null;
+        }
+
+        LOG.info("Creating a " + endpoint.getInterfaces().toArray()[0] + " client, wsdl address is "
+                 + OsgiUtils.getProperty(endpoint, Constants.WSDL_CONFIG_PREFIX));
+
+        String serviceNs = OsgiUtils.getProperty(endpoint, Constants.WSDL_SERVICE_NAMESPACE);
+        if (serviceNs == null) {
+            serviceNs = PackageUtils.getNamespace(PackageUtils.getPackageName(iClass));
+        }
+        String serviceName = OsgiUtils.getProperty(endpoint, Constants.WSDL_SERVICE_NAME);
+        if (serviceName == null) {
+            serviceName = iClass.getSimpleName();
+        }
+        QName serviceQname = getServiceQName(iClass, endpoint.getProperties(),
+                                             Constants.WSDL_SERVICE_NAMESPACE,
+                                             Constants.WSDL_SERVICE_NAME);
+        QName portQname = getPortQName(serviceQname.getNamespaceURI(),
+                endpoint.getProperties(), Constants.WSDL_PORT_NAME);
+        Service service = createWebService(wsdlAddress, serviceQname);
+        Object proxy = getProxy(portQname == null ? service.getPort(iClass) : service.getPort(portQname, iClass),
+                                iClass);
+        // MARC: FIXME!!!! getDistributionProvider().addRemoteService(serviceReference);
+        return proxy;
+    }
+
+    // Isolated so that it can be overridden for test purposes.
+    Service createWebService(URL wsdlAddress, QName serviceQname) {
+        return Service.create(wsdlAddress, serviceQname);
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Endpoint exportService(Object serviceO,
+                                  BundleContext serviceContext,
+                                  Map<String, Object> sd,
+                                  Class[] exportedInterfaces) {
+        Class<?> iClass = exportedInterfaces[0];
+        String location = OsgiUtils.getProperty(sd, Constants.WSDL_LOCATION);
+        if (location == null) {
+            throw new RuntimeException("WSDL location property is unavailable");
+        }
+        URL wsdlURL = serviceContext.getBundle().getResource(location);
+        if (wsdlURL == null) {
+            throw new RuntimeException("WSDL resource at " + location + " is unavailable");
+        }
+
+        String address = getServerAddress(sd, iClass);
+        String contextRoot = getServletContextRoot(sd);
+        if (address == null && contextRoot == null) {
+            throw new RuntimeException("Remote address is unavailable");
+        }
+
+        LOG.info("Creating a " + iClass.getName() + " endpoint from CXF PublishHook, address is " + address);
+
+        DataBinding databinding = new JAXBDataBinding();
+        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
+        final Long sid = (Long) sd.get(RemoteConstants.ENDPOINT_SERVICE_ID);
+        Bus bus = createBus(sid, serviceContext, contextRoot);
+        factory.setBus(bus);
+        factory.setServiceClass(iClass);
+        factory.setAddress(address != null ? address : "/");
+        factory.getServiceFactory().setDataBinding(databinding);
+        factory.setServiceBean(serviceO);
+
+        addWsInterceptorsFeaturesProps(factory, serviceContext, sd);
+
+        setWsdlProperties(factory, serviceContext, sd, true);
+
+        String[] intents = intentManager.applyIntents(factory.getFeatures(), factory, sd);
+
+        EndpointDescription epd = createEndpointDesc(sd,
+                                                     new String[]{Constants.WS_CONFIG_TYPE},
+                                                     address, intents);
+        return createServerFromFactory(factory, epd);
+    }
+
+    private String getWsdlAddress(EndpointDescription endpoint, Class<?> iClass) {
+        String address = OsgiUtils.getProperty(endpoint, Constants.WSDL_CONFIG_PREFIX);
+        if (address == null) {
+            address = httpServiceManager.getDefaultAddress(iClass);
+            if (address != null) {
+                address += "?wsdl";
+            }
+        }
+        return address;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/DefaultIntentMapFactory.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/DefaultIntentMapFactory.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/DefaultIntentMapFactory.java
new file mode 100644
index 0000000..7e0dd2e
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/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.dsw.qos;
+
+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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManager.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManager.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManager.java
new file mode 100644
index 0000000..ecaf070
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManager.java
@@ -0,0 +1,31 @@
+/**
+ * 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.dsw.qos;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.endpoint.AbstractEndpointFactory;
+import org.apache.cxf.feature.Feature;
+
+public interface IntentManager {
+
+    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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManagerImpl.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManagerImpl.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManagerImpl.java
new file mode 100644
index 0000000..e161ef0
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentManagerImpl.java
@@ -0,0 +1,155 @@
+/**
+ * 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.dsw.qos;
+
+import java.util.ArrayList;
+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.endpoint.AbstractEndpointFactory;
+import org.apache.cxf.feature.Feature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IntentManagerImpl implements IntentManager {
+
+    static final Logger LOG = LoggerFactory.getLogger(IntentManagerImpl.class);
+    private static final String PROVIDED_INTENT_VALUE = "PROVIDED";
+
+    private final IntentMap intentMap;
+    private final long maxIntentWaitTime;
+
+    public IntentManagerImpl(IntentMap intentMap) {
+        this(intentMap, 0);
+    }
+
+    public IntentManagerImpl(IntentMap intentMap, int maxIntentWaitTime) {
+        this.intentMap = intentMap;
+        this.maxIntentWaitTime = maxIntentWaitTime;
+    }
+
+    public String[] applyIntents(List<Feature> features, AbstractEndpointFactory factory,
+                                 Map<String, Object> props) throws IntentUnsatisfiedException {
+        Set<String> requestedIntents = IntentUtils.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 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 = IntentUtils.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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentMap.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentMap.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentMap.java
new file mode 100644
index 0000000..5ed4ef6
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/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.dsw.qos;
+
+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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentTracker.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentTracker.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentTracker.java
new file mode 100644
index 0000000..e1ceaaa
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentTracker.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.dsw.qos;
+
+import org.apache.cxf.dosgi.dsw.Constants;
+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("(" + Constants.INTENT_NAME_PROP + "=*)");
+        } catch (InvalidSyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference) {
+        String intentName = (String) reference.getProperty(Constants.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(Constants.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/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentUtils.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentUtils.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentUtils.java
new file mode 100644
index 0000000..31b1e42
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/qos/IntentUtils.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.dsw.qos;
+
+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.cxf.dosgi.dsw.Constants;
+import org.apache.cxf.dosgi.dsw.util.OsgiUtils;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+
+public final class IntentUtils {
+
+    private IntentUtils() {
+        // never constructed
+    }
+
+    public static String[] mergeArrays(String[] a1, String[] a2) {
+        if (a1 == null) {
+            return a2;
+        }
+        if (a2 == null) {
+            return a1;
+        }
+
+        List<String> list = new ArrayList<String>(a1.length + a2.length);
+        Collections.addAll(list, a1);
+        for (String s : a2) {
+            if (!list.contains(s)) {
+                list.add(s);
+            }
+        }
+
+        return list.toArray(new String[list.size()]);
+    }
+
+    public 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(Constants.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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/util/OsgiUtils.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/util/OsgiUtils.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/util/OsgiUtils.java
new file mode 100644
index 0000000..9acd0f0
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/util/OsgiUtils.java
@@ -0,0 +1,132 @@
+/**
+ * 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.dsw.util;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("deprecation")
+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;
+    }
+
+    /**
+     * Tries to retrieve the version of iClass via the PackageAdmin.
+     *
+     * @param iClass tThe interface for which the version should be found
+     * @param bc any valid BundleContext
+     * @return the version of the interface or "0.0.0" if no version information could be found or an error
+     *         occurred during the retrieval
+     */
+    public static String getVersion(Class<?> iClass, BundleContext bc) {
+        ServiceReference<PackageAdmin> paRef = bc.getServiceReference(PackageAdmin.class);
+        if (paRef != null) {
+            PackageAdmin pa = bc.getService(paRef);
+            try {
+                Bundle b = pa.getBundle(iClass);
+                if (b == null) {
+                    LOG.info("Unable to find interface version for interface " + iClass.getName()
+                            + ". Falling back to 0.0.0");
+                    return "0.0.0";
+                }
+                LOG.debug("Interface source bundle: {}", b.getSymbolicName());
+
+                ExportedPackage[] ep = pa.getExportedPackages(b);
+                LOG.debug("Exported Packages of the source bundle: {}", (Object)ep);
+
+                String pack = iClass.getPackage().getName();
+                LOG.debug("Looking for Package: {}", pack);
+                if (ep != null) {
+                    for (ExportedPackage p : ep) {
+                        if (p != null
+                            && pack.equals(p.getName())) {
+                            LOG.debug("found package -> Version: {}", p.getVersion());
+                            return p.getVersion().toString();
+                        }
+                    }
+                }
+            } finally {
+                if (pa != null) {
+                    bc.ungetService(paRef);
+                }
+            }
+        } else {
+            LOG.error("Was unable to obtain the package admin service -> can't resolve interface versions");
+        }
+
+        LOG.info("Unable to find interface version for interface " + iClass.getName()
+                 + ". Falling back to 0.0.0");
+        return "0.0.0";
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/1425743f/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/util/StringPlus.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/util/StringPlus.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/util/StringPlus.java
new file mode 100644
index 0000000..dbb4cda
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/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.dsw.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/1425743f/cxf-dsw/src/main/resources/service-decoration.xsd
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/resources/service-decoration.xsd b/cxf-dsw/src/main/resources/service-decoration.xsd
new file mode 100644
index 0000000..66e8d30
--- /dev/null
+++ b/cxf-dsw/src/main/resources/service-decoration.xsd
@@ -0,0 +1,67 @@
+<?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.
+-->
+<schema targetNamespace="http://cxf.apache.org/xmlns/service-decoration/1.0.0" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://cxf.apache.org/xmlns/service-decoration/1.0.0">
+    <element name="service-decorations" type="tns:ServiceDecorationsType"></element>
+
+    <complexType name="ServiceDecorationsType">
+        <sequence>
+            <element maxOccurs="unbounded" minOccurs="0"
+                ref="tns:service-decoration">
+            </element>
+        </sequence>
+    </complexType>
+
+    <complexType name="ServiceDecorationType">
+        <sequence>
+            <element maxOccurs="unbounded" minOccurs="0"
+                ref="tns:match">
+            </element>
+        </sequence>
+    </complexType>
+
+    <complexType name="MatchType">
+        <sequence>
+            <element maxOccurs="unbounded" minOccurs="0"
+                ref="tns:match-property">
+            </element>
+            <element maxOccurs="unbounded" minOccurs="0"
+                ref="tns:add-property">
+            </element>
+        </sequence>
+        <attribute name="interface" type="string"></attribute>
+    </complexType>
+
+    <complexType name="MatchPropertyType">
+        <attribute name="name" type="string"></attribute>
+        <attribute name="value" type="string"></attribute>
+    </complexType>
+
+    <complexType name="AddPropertyType">
+        <attribute name="name" type="string"></attribute>
+        <attribute name="value" type="string"></attribute>
+        <attribute name="type" type="string"></attribute>
+    </complexType>
+    <element name="service-decoration"
+        type="tns:ServiceDecorationType">
+    </element>
+    <element name="match" type="tns:MatchType"></element>
+    <element name="match-property" type="tns:MatchPropertyType"></element>
+    <element name="add-property" type="tns:AddPropertyType"></element>
+</schema>
\ No newline at end of file


Mime
View raw message