You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by cs...@apache.org on 2016/07/01 12:09:10 UTC
[4/5] cxf-dosgi git commit: [DOSGI-242] Refactor provider, Cleanup
http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/79bb9a43/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
deleted file mode 100644
index 6171a53..0000000
--- a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * 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/79bb9a43/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
deleted file mode 100644
index 5bf16d7..0000000
--- a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/WsdlConfigurationTypeHandler.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- * 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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/AbstractPojoConfigurationTypeHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/AbstractPojoConfigurationTypeHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/AbstractPojoConfigurationTypeHandler.java
new file mode 100644
index 0000000..aa543e0
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/AbstractPojoConfigurationTypeHandler.java
@@ -0,0 +1,246 @@
+/**
+ * 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.pojo;
+
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.aries.rsa.spi.DistributionProvider;
+import org.apache.aries.rsa.spi.Endpoint;
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.dosgi.dsw.httpservice.HttpServiceManager;
+import org.apache.cxf.dosgi.dsw.osgi.Constants;
+import org.apache.cxf.dosgi.dsw.qos.IntentManager;
+import org.apache.cxf.dosgi.dsw.qos.IntentUtils;
+import org.apache.cxf.dosgi.dsw.util.ClassUtils;
+import org.apache.cxf.dosgi.dsw.util.OsgiUtils;
+import org.apache.cxf.dosgi.dsw.util.ServerWrapper;
+import org.apache.cxf.dosgi.dsw.util.StringPlus;
+import org.apache.cxf.endpoint.AbstractEndpointFactory;
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory;
+import org.apache.cxf.frontend.ClientFactoryBean;
+import org.apache.cxf.frontend.ServerFactoryBean;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.interceptor.Interceptor;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+
+public abstract class AbstractPojoConfigurationTypeHandler implements DistributionProvider {
+ protected BundleContext bundleContext;
+ protected IntentManager intentManager;
+ protected HttpServiceManager httpServiceManager;
+
+ public AbstractPojoConfigurationTypeHandler(BundleContext dswBC, IntentManager intentManager,
+ HttpServiceManager httpServiceManager) {
+ this.bundleContext = dswBC;
+ this.intentManager = intentManager;
+ this.httpServiceManager = httpServiceManager;
+ }
+
+ protected Object getProxy(Object serviceProxy, Class<?> iType) {
+ return Proxy.newProxyInstance(iType.getClassLoader(), new Class[] {
+ iType
+ }, new ServiceInvocationHandler(serviceProxy, iType));
+ }
+
+ protected EndpointDescription createEndpointDesc(Map<String, Object> props,
+ String[] importedConfigs,
+ String address,
+ String[] intents) {
+ props.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, importedConfigs);
+ for (String configurationType : importedConfigs) {
+ if (Constants.WS_CONFIG_TYPE.equals(configurationType)) {
+ props.put(Constants.WS_ADDRESS_PROPERTY, address);
+ } else if (Constants.RS_CONFIG_TYPE.equals(configurationType)) {
+ props.put(Constants.RS_ADDRESS_PROPERTY, address);
+ } else if (Constants.WS_CONFIG_TYPE_OLD.equals(configurationType)) {
+ props.put(Constants.WS_ADDRESS_PROPERTY_OLD, address);
+ props.put(Constants.WS_ADDRESS_PROPERTY, address);
+ }
+ }
+ String[] sIntents = StringPlus.normalize(props.get(RemoteConstants.SERVICE_INTENTS));
+ String[] allIntents = IntentUtils.mergeArrays(intents, sIntents);
+ props.put(RemoteConstants.SERVICE_INTENTS, allIntents);
+ props.put(RemoteConstants.ENDPOINT_ID, address);
+ return new EndpointDescription(props);
+ }
+
+ protected void setCommonWsdlProperties(AbstractWSDLBasedEndpointFactory factory, BundleContext context,
+ Map<String, Object> sd, boolean wsdlType) {
+ String location = OsgiUtils.getProperty(sd, wsdlType ? Constants.WSDL_LOCATION : Constants.WS_WSDL_LOCATION);
+ if (location != null) {
+ URL wsdlURL = context.getBundle().getResource(location);
+ if (wsdlURL != null) {
+ factory.setWsdlURL(wsdlURL.toString());
+ }
+ QName serviceName = getServiceQName(null, sd,
+ wsdlType ? Constants.WSDL_SERVICE_NAMESPACE : Constants.WS_WSDL_SERVICE_NAMESPACE,
+ wsdlType ? Constants.WSDL_SERVICE_NAME : Constants.WS_WSDL_SERVICE_NAME);
+ if (serviceName != null) {
+ factory.setServiceName(serviceName);
+ QName portName = getPortQName(serviceName.getNamespaceURI(), sd,
+ wsdlType ? Constants.WSDL_PORT_NAME : Constants.WS_WSDL_PORT_NAME);
+ if (portName != null) {
+ factory.setEndpointName(portName);
+ }
+ }
+ }
+ }
+
+ protected void setWsdlProperties(ServerFactoryBean factory, BundleContext callingContext, Map<String, Object> sd,
+ boolean wsdlType) {
+ setCommonWsdlProperties(factory, callingContext, sd, wsdlType);
+ }
+
+ protected void setClientWsdlProperties(ClientFactoryBean factory, BundleContext dswContext, Map<String, Object> sd,
+ boolean wsdlType) {
+ setCommonWsdlProperties(factory, dswContext, sd, wsdlType);
+ }
+
+ protected static QName getServiceQName(Class<?> iClass, Map<String, Object> sd, String nsPropName,
+ String namePropName) {
+ String serviceNs = OsgiUtils.getProperty(sd, nsPropName);
+ String serviceName = OsgiUtils.getProperty(sd, namePropName);
+ if (iClass == null && (serviceNs == null || serviceName == null)) {
+ return null;
+ }
+ if (serviceNs == null) {
+ serviceNs = PackageUtils.getNamespace(PackageUtils.getPackageName(iClass));
+ }
+ if (serviceName == null) {
+ serviceName = iClass.getSimpleName();
+ }
+ return new QName(serviceNs, serviceName);
+ }
+
+ protected static QName getPortQName(String ns, Map<String, Object> sd, String propName) {
+ String portName = OsgiUtils.getProperty(sd, propName);
+ if (portName == null) {
+ return null;
+ }
+ return new QName(ns, portName);
+ }
+
+ protected String getClientAddress(Map<String, Object> sd) {
+ return OsgiUtils.getFirstNonEmptyStringProperty(sd, RemoteConstants.ENDPOINT_ID,
+ Constants.WS_ADDRESS_PROPERTY,
+ Constants.WS_ADDRESS_PROPERTY_OLD,
+ Constants.RS_ADDRESS_PROPERTY);
+ }
+
+ protected String getServerAddress(Map<String, Object> sd, Class<?> iClass) {
+ String address = getClientAddress(sd);
+ return address == null ? httpServiceManager.getDefaultAddress(iClass) : address;
+ }
+
+ public String getServletContextRoot(Map<String, Object> sd) {
+ return OsgiUtils.getFirstNonEmptyStringProperty(sd,
+ Constants.WS_HTTP_SERVICE_CONTEXT,
+ Constants.WS_HTTP_SERVICE_CONTEXT_OLD,
+ Constants.WSDL_HTTP_SERVICE_CONTEXT,
+ Constants.RS_HTTP_SERVICE_CONTEXT);
+ }
+
+
+ protected Bus createBus(Long sid, BundleContext callingContext, String contextRoot) {
+ Bus bus = BusFactory.newInstance().createBus();
+ if (contextRoot != null) {
+ httpServiceManager.registerServlet(bus, contextRoot, callingContext, sid);
+ }
+ return bus;
+ }
+
+ protected Endpoint createServerFromFactory(ServerFactoryBean factory, EndpointDescription epd) {
+ ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(ServerFactoryBean.class.getClassLoader());
+ Server server = factory.create();
+ return new ServerWrapper(epd, server);
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ }
+ }
+
+ protected static void addWsInterceptorsFeaturesProps(AbstractEndpointFactory factory, BundleContext callingContext,
+ Map<String, Object> sd) {
+ addInterceptors(factory, callingContext, sd, Constants.WS_IN_INTERCEPTORS_PROP_KEY);
+ addInterceptors(factory, callingContext, sd, Constants.WS_OUT_INTERCEPTORS_PROP_KEY);
+ addInterceptors(factory, callingContext, sd, Constants.WS_OUT_FAULT_INTERCEPTORS_PROP_KEY);
+ addInterceptors(factory, callingContext, sd, Constants.WS_IN_FAULT_INTERCEPTORS_PROP_KEY);
+ addFeatures(factory, callingContext, sd, Constants.WS_FEATURES_PROP_KEY);
+ addContextProperties(factory, sd, Constants.WS_CONTEXT_PROPS_PROP_KEY);
+ }
+
+ protected static void addRsInterceptorsFeaturesProps(AbstractEndpointFactory factory, BundleContext callingContext,
+ Map<String, Object> sd) {
+ addInterceptors(factory, callingContext, sd, Constants.RS_IN_INTERCEPTORS_PROP_KEY);
+ addInterceptors(factory, callingContext, sd, Constants.RS_OUT_INTERCEPTORS_PROP_KEY);
+ addInterceptors(factory, callingContext, sd, Constants.RS_OUT_FAULT_INTERCEPTORS_PROP_KEY);
+ addInterceptors(factory, callingContext, sd, Constants.RS_IN_FAULT_INTERCEPTORS_PROP_KEY);
+ addFeatures(factory, callingContext, sd, Constants.RS_FEATURES_PROP_KEY);
+ addContextProperties(factory, sd, Constants.RS_CONTEXT_PROPS_PROP_KEY);
+ }
+
+ private static void addInterceptors(AbstractEndpointFactory factory, BundleContext callingContext,
+ Map<String, Object> sd, String propName) {
+ List<Object> providers = ClassUtils.loadProviderClasses(callingContext, sd, propName);
+ boolean in = propName.contains("in.interceptors");
+ boolean out = propName.contains("out.interceptors");
+ boolean inFault = propName.contains("in.fault.interceptors");
+ boolean outFault = propName.contains("out.fault.interceptors");
+ for (Object provider : providers) {
+ Interceptor<?> interceptor = (Interceptor<?>) provider;
+ if (in) {
+ factory.getInInterceptors().add(interceptor);
+ } else if (out) {
+ factory.getOutInterceptors().add(interceptor);
+ } else if (inFault) {
+ factory.getInFaultInterceptors().add(interceptor);
+ } else if (outFault) {
+ factory.getOutFaultInterceptors().add(interceptor);
+ }
+ }
+ }
+
+ private static void addFeatures(AbstractEndpointFactory factory, BundleContext callingContext,
+ Map<String, Object> sd, String propName) {
+ List<Object> providers = ClassUtils.loadProviderClasses(callingContext, sd, propName);
+ if (!providers.isEmpty()) {
+ factory.getFeatures().addAll(CastUtils.cast(providers, AbstractFeature.class));
+ }
+ }
+
+ private static void addContextProperties(AbstractEndpointFactory factory, Map<String, Object> sd, String propName) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> props = (Map<String, Object>)sd.get(propName);
+ if (props != null) {
+ factory.getProperties(true).putAll(props);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf-dosgi/blob/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/PojoConfigurationTypeHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/PojoConfigurationTypeHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/PojoConfigurationTypeHandler.java
new file mode 100644
index 0000000..a0784fb
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/PojoConfigurationTypeHandler.java
@@ -0,0 +1,173 @@
+/**
+ * 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.pojo;
+
+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.httpservice.HttpServiceManager;
+import org.apache.cxf.dosgi.dsw.osgi.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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/ServiceInvocationHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/ServiceInvocationHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/ServiceInvocationHandler.java
new file mode 100644
index 0000000..3928c7d
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/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.pojo;
+
+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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/WsdlConfigurationTypeHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/WsdlConfigurationTypeHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/WsdlConfigurationTypeHandler.java
new file mode 100644
index 0000000..b818354
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/pojo/WsdlConfigurationTypeHandler.java
@@ -0,0 +1,161 @@
+/**
+ * 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.pojo;
+
+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.httpservice.HttpServiceManager;
+import org.apache.cxf.dosgi.dsw.osgi.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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSPojoConfigurationTypeHandler.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSPojoConfigurationTypeHandler.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSPojoConfigurationTypeHandler.java
new file mode 100644
index 0000000..49e9d39
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSPojoConfigurationTypeHandler.java
@@ -0,0 +1,204 @@
+/**
+ * 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.rest;
+
+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.handlers.pojo.AbstractPojoConfigurationTypeHandler;
+import org.apache.cxf.dosgi.dsw.httpservice.HttpServiceManager;
+import org.apache.cxf.dosgi.dsw.osgi.Constants;
+import org.apache.cxf.dosgi.dsw.qos.IntentManager;
+import org.apache.cxf.dosgi.dsw.util.OsgiUtils;
+import org.apache.cxf.dosgi.dsw.util.ServerWrapper;
+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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSUtils.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSUtils.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSUtils.java
new file mode 100644
index 0000000..c03a29f
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/JaxRSUtils.java
@@ -0,0 +1,122 @@
+/**
+ * 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.rest;
+
+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.ClassUtils;
+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.osgi.Constants.RS_DATABINDING_PROP_KEY))) {
+ providers.add(new AegisElementProvider());
+ }
+
+ providers.addAll(ClassUtils.loadProviderClasses(callingContext,
+ sd,
+ org.apache.cxf.dosgi.dsw.osgi.Constants.RS_PROVIDER_PROP_KEY));
+
+ Object globalQueryProp = sd.get(org.apache.cxf.dosgi.dsw.osgi.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.osgi.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.osgi.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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/HttpServiceManager.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/HttpServiceManager.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/HttpServiceManager.java
new file mode 100644
index 0000000..f6ebda1
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/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.httpservice;
+
+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);
+ }
+ }
+
+ 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;
+ }
+
+ 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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/LocalHostUtil.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/LocalHostUtil.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/LocalHostUtil.java
new file mode 100644
index 0000000..f2fefe9
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/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.dsw.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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/SecurityDelegatingHttpContext.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/SecurityDelegatingHttpContext.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/httpservice/SecurityDelegatingHttpContext.java
new file mode 100644
index 0000000..042f2d5
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/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.dsw.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/79bb9a43/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/osgi/Activator.java b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/osgi/Activator.java
new file mode 100644
index 0000000..13ef30f
--- /dev/null
+++ b/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/osgi/Activator.java
@@ -0,0 +1,153 @@
+/**
+ * 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.osgi;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.aries.rsa.spi.DistributionProvider;
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.dosgi.dsw.handlers.CXFDistributionProvider;
+import org.apache.cxf.dosgi.dsw.httpservice.HttpServiceManager;
+import org.apache.cxf.dosgi.dsw.qos.DefaultIntentMapFactory;
+import org.apache.cxf.dosgi.dsw.qos.IntentManager;
+import org.apache.cxf.dosgi.dsw.qos.IntentManagerImpl;
+import org.apache.cxf.dosgi.dsw.qos.IntentMap;
+import org.apache.cxf.dosgi.dsw.qos.IntentTracker;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// registered as spring bean -> start / stop called accordingly
+public class Activator implements ManagedService, BundleActivator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Activator.class);
+ private static final int DEFAULT_INTENT_TIMEOUT = 30000;
+ private static final String CONFIG_SERVICE_PID = "cxf-dsw";
+ private ServiceRegistration<?> rsaFactoryReg;
+ private ServiceRegistration<?> decoratorReg;
+ private IntentTracker intentTracker;
+ private HttpServiceManager httpServiceManager;
+ private BundleContext bc;
+ private BundleListener bundleListener;
+ private Dictionary<String, Object> curConfiguration;
+ private Bus bus;
+
+ public void start(BundleContext bundlecontext) throws Exception {
+ LOG.debug("RemoteServiceAdmin Implementation is starting up");
+ this.bc = bundlecontext;
+ // Disable the fast infoset as it's not compatible (yet) with OSGi
+ System.setProperty("org.apache.cxf.nofastinfoset", "true");
+ curConfiguration = getDefaultConfig();
+ init(curConfiguration);
+ registerManagedService(bc);
+ }
+
+ private Dictionary<String, Object> getDefaultConfig() {
+ return new Hashtable<String, Object>();
+ }
+
+ private synchronized void init(Dictionary<String, Object> config) {
+ bus = BusFactory.newInstance().createBus();
+
+ String httpBase = (String) config.get(org.apache.cxf.dosgi.dsw.osgi.Constants.HTTP_BASE);
+ String cxfServletAlias = (String) config.get(org.apache.cxf.dosgi.dsw.osgi.Constants.CXF_SERVLET_ALIAS);
+
+ IntentMap intentMap = new IntentMap(new DefaultIntentMapFactory().create());
+ intentTracker = new IntentTracker(bc, intentMap);
+ intentTracker.open();
+ IntentManager intentManager = new IntentManagerImpl(intentMap, DEFAULT_INTENT_TIMEOUT);
+ httpServiceManager = new HttpServiceManager(bc, httpBase, cxfServletAlias);
+ DistributionProvider cxfProvider
+ = new CXFDistributionProvider(bc, intentManager, httpServiceManager);
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ String[] supportedIntents = intentMap.keySet().toArray(new String[] {});
+ props.put(Constants.REMOTE_INTENTS_SUPPORTED, supportedIntents);
+ props.put(Constants.REMOTE_CONFIGS_SUPPORTED, cxfProvider.getSupportedTypes());
+ rsaFactoryReg = bc.registerService(DistributionProvider.class.getName(), cxfProvider, props);
+ }
+
+ private synchronized void uninit() {
+ if (decoratorReg != null) {
+ decoratorReg.unregister();
+ decoratorReg = null;
+ }
+ if (bundleListener != null) {
+ bc.removeBundleListener(bundleListener);
+ bundleListener = null;
+ }
+ if (rsaFactoryReg != null) {
+ // This also triggers the unimport and unexport of the remote services
+ rsaFactoryReg.unregister();
+ rsaFactoryReg = null;
+ }
+ if (httpServiceManager != null) {
+ httpServiceManager.close();
+ httpServiceManager = null;
+ }
+ if (intentTracker != null) {
+ intentTracker.close();
+ intentTracker = null;
+ }
+ }
+
+ private void registerManagedService(BundleContext bundlecontext) {
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put(Constants.SERVICE_PID, CONFIG_SERVICE_PID);
+ // No need to store the registration. Will be unregistered in stop by framework
+ bundlecontext.registerService(ManagedService.class.getName(), this, props);
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ LOG.debug("RemoteServiceAdmin Implementation is shutting down now");
+ uninit();
+ shutdownCXFBus();
+ }
+
+ /**
+ * Causes also the shutdown of the embedded HTTP server
+ */
+ private void shutdownCXFBus() {
+ if (bus != null) {
+ LOG.debug("Shutting down the CXF Bus");
+ bus.shutdown(true);
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public synchronized void updated(Dictionary config) throws ConfigurationException {
+ LOG.debug("RemoteServiceAdmin Implementation configuration is updated with {}", config);
+ // config is null if it doesn't exist, is being deleted or has not yet been loaded
+ // in which case we run with defaults (just like we do manually when bundle is first started)
+ Dictionary<String, Object> configMap = config == null ? getDefaultConfig() : config;
+ if (!configMap.equals(curConfiguration)) { // only if something actually changed
+ curConfiguration = configMap;
+ uninit();
+ init(configMap);
+ }
+ }
+
+}