[CXF-5107] SSL example and support for Conduit features
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java
index fbbdcd3..f854691 100644
--- a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentManager.java
@@ -18,6 +18,7 @@
*/
package org.apache.cxf.dosgi.common.intent;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -37,4 +38,8 @@
Set<String> requiredIntents, //
IntentHandler ... handlers)
throws IntentUnsatisfiedException;
+
+ <T> List<T> getIntents(Class<? extends T> type, List<Object> intents);
+ <T> T getIntent(Class<? extends T> type, List<Object> intents);
+ List<Object> getIntents(Set<String> requiredIntents);
}
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/DefaultIntentsHandler.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/DefaultIntentsHandler.java
index 396830b..8242829 100644
--- a/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/DefaultIntentsHandler.java
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/DefaultIntentsHandler.java
@@ -22,7 +22,6 @@
import org.apache.cxf.databinding.DataBinding;
import org.apache.cxf.dosgi.common.intent.IntentHandler;
import org.apache.cxf.endpoint.AbstractEndpointFactory;
-import org.apache.cxf.feature.Feature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,11 +41,6 @@
LOG.info(prefix + "binding config: " + bindingCfg);
factory.setBindingConfig(bindingCfg);
return true;
- } else if (intent instanceof Feature) {
- Feature feature = (Feature)intent;
- LOG.info(prefix + "feature: " + feature);
- factory.getFeatures().add(feature);
- return true;
} else {
return false;
}
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/IntentManagerImpl.java b/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/IntentManagerImpl.java
index 5b3d556..b27f2c6 100644
--- a/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/IntentManagerImpl.java
+++ b/common/src/main/java/org/apache/cxf/dosgi/common/intent/impl/IntentManagerImpl.java
@@ -31,9 +31,9 @@
import org.apache.aries.rsa.spi.IntentUnsatisfiedException;
import org.apache.cxf.dosgi.common.intent.IntentHandler;
import org.apache.cxf.dosgi.common.intent.IntentManager;
-import org.apache.cxf.dosgi.common.intent.IntentProvider;
import org.apache.cxf.dosgi.common.util.OsgiUtils;
import org.apache.cxf.endpoint.AbstractEndpointFactory;
+import org.apache.cxf.feature.Feature;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
@@ -90,7 +90,7 @@
public synchronized void removeIntent(Object intent, String intentName) {
intentMap.remove(intentName);
}
-
+
@SuppressWarnings("unchecked")
@Override
public synchronized void applyIntents(AbstractEndpointFactory factory,
@@ -101,6 +101,7 @@
if (!missingIntents.isEmpty()) {
throw new IntentUnsatisfiedException(missingIntents.iterator().next());
}
+ List<Feature> features = new ArrayList<Feature>();
List<IntentHandler> allHandlers = new ArrayList<IntentHandler>();
allHandlers.add(new DefaultIntentsHandler());
allHandlers.addAll(Arrays.asList(handlers));
@@ -109,30 +110,36 @@
if (intent instanceof Callable<?>) {
try {
List<Object> intents = ((Callable<List<Object>>)intent).call();
- applyIntents(factory, intentName, intents, allHandlers);
+ applyIntents(factory, features, intentName, intents, allHandlers);
} catch (Exception e) {
throw new RuntimeException(e);
}
- } else if (intent instanceof IntentProvider) {
- applyIntents(factory, intentName, ((IntentProvider)intent).getIntents(), allHandlers);
} else {
- applyIntent(factory, intentName, intent, allHandlers);
+ applyIntent(factory, features, intentName, intent, allHandlers);
}
}
+ factory.setFeatures(features);
}
- private void applyIntents(AbstractEndpointFactory factory,
+ private void applyIntents(AbstractEndpointFactory factory,
+ List<Feature> features,
String intentName,
List<Object> intents,
List<IntentHandler> handlers) {
for (Object intent : intents) {
- applyIntent(factory, intentName, intent, handlers);
+ applyIntent(factory, features, intentName, intent, handlers);
}
}
- private void applyIntent(AbstractEndpointFactory factory, String intentName, Object intent,
+ private void applyIntent(AbstractEndpointFactory factory, List<Feature> features, String intentName, Object intent,
List<IntentHandler> handlers) {
+ if (intent instanceof Feature) {
+ Feature feature = (Feature)intent;
+ LOG.info("Applying intent: " + intentName + " via feature: " + feature);
+ features.add(feature);
+ return;
+ }
for (IntentHandler handler : handlers) {
if (handler.apply(factory, intentName, intent)) {
return;
@@ -141,6 +148,48 @@
LOG.info("No mapping for intent: " + intentName);
throw new IntentUnsatisfiedException(intentName);
}
+
+ @SuppressWarnings("unchecked")
+ public synchronized List<Object> getIntents(Set<String> requiredIntents) {
+ String[] intentNames = assertAllIntentsSupported(requiredIntents);
+ List<Object> intents = new ArrayList<Object>();
+ for (String intentName : intentNames) {
+ Object intent = intentMap.get(intentName);
+ if (intent instanceof Callable<?>) {
+ try {
+ List<Object> curIntents = ((Callable<List<Object>>)intent).call();
+ intents.addAll(curIntents);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ } else {
+ intents.add(intent);
+ }
+ }
+ return intents;
+ }
+
+ public <T> T getIntent(Class<? extends T> type, List<Object> intents) {
+ List<T> selectedIntents = getIntents(type, intents);
+ if (selectedIntents.isEmpty()) {
+ return null;
+ }
+ if (selectedIntents.size() > 1) {
+ LOG.warn("More than one intent of type " + type + " present. Using only the first one.");
+ }
+ return (T)selectedIntents.iterator().next();
+ }
+
+ public <T> List<T> getIntents(Class<? extends T> type, List<Object> intents) {
+ List<T> result = new ArrayList<T>();
+ for (Object intent : intents) {
+ if (type.isInstance(intent)) {
+ result.add(type.cast(intent));
+ }
+ }
+ return result;
+ }
public synchronized String[] assertAllIntentsSupported(Set<String> requiredIntents) {
long endTime = System.currentTimeMillis() + maxIntentWaitTime;
diff --git a/parent/pom.xml b/parent/pom.xml
index 3ce54d2..b551395 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -262,7 +262,7 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>3.0.1</version>
+ <version>3.2.0</version>
<extensions>true</extensions>
<configuration>
<obrRepository>NONE</obrRepository>
@@ -331,6 +331,7 @@
</snapshots>
</repository>
+
</repositories>
<pluginRepositories>
diff --git a/provider-rs/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/RsProvider.java b/provider-rs/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/RsProvider.java
index 6c0fed9..350ab7f 100644
--- a/provider-rs/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/RsProvider.java
+++ b/provider-rs/src/main/java/org/apache/cxf/dosgi/dsw/handlers/rest/RsProvider.java
@@ -23,15 +23,23 @@
import static org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_INTENTS_SUPPORTED;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
import org.apache.aries.rsa.spi.DistributionProvider;
import org.apache.aries.rsa.spi.Endpoint;
import org.apache.aries.rsa.spi.IntentUnsatisfiedException;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
+import org.apache.cxf.binding.BindingConfiguration;
+import org.apache.cxf.databinding.DataBinding;
import org.apache.cxf.dosgi.common.httpservice.HttpServiceManager;
import org.apache.cxf.dosgi.common.intent.IntentManager;
import org.apache.cxf.dosgi.common.proxy.ProxyFactory;
@@ -39,6 +47,8 @@
import org.apache.cxf.dosgi.common.util.ServerEndpoint;
import org.apache.cxf.endpoint.AbstractEndpointFactory;
import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.feature.Feature;
+import org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
@@ -80,21 +90,22 @@
BundleContext consumerContext,
Class[] interfaces,
EndpointDescription endpoint) {
- Set<String> intents = intentManager.getImported(endpoint.getProperties());
- intentManager.assertAllIntentsSupported(intents);
+ Set<String> intentNames = intentManager.getImported(endpoint.getProperties());
+ List<Object> intents = intentManager.getIntents(intentNames);
Class<?> iClass = interfaces[0];
String address = OsgiUtils.getProperty(endpoint, RsConstants.RS_ADDRESS_PROPERTY);
if (address == null) {
LOG.warn("Remote address is unavailable");
return null;
}
- return createJaxrsProxy(address, iClass, null, endpoint);
+ return createJaxrsProxy(address, iClass, null, endpoint, intents);
}
private Object createJaxrsProxy(String address,
Class<?> iClass,
ClassLoader loader,
- EndpointDescription endpoint) {
+ EndpointDescription endpoint,
+ List<Object> intents) {
JAXRSClientFactoryBean factory = new JAXRSClientFactoryBean();
factory.setAddress(address);
if (loader != null) {
@@ -102,10 +113,7 @@
}
addContextProperties(factory, endpoint.getProperties(), RsConstants.RS_CONTEXT_PROPS_PROP_KEY);
factory.setServiceClass(iClass);
- Set<String> intents = intentManager.getImported(endpoint.getProperties());
- intentManager.applyIntents(factory, intents, new ProviderIntentHandler());
- // Apply providers
- factory.setProviders(factory.getProviders());
+ applyIntents(intents, factory);
return ProxyFactory.create(factory.create(), iClass);
}
@@ -129,8 +137,8 @@
}
}
final Long sid = (Long) endpointProps.get(RemoteConstants.ENDPOINT_SERVICE_ID);
- Set<String> intents = intentManager.getExported(endpointProps);
- intentManager.assertAllIntentsSupported(intents);
+ Set<String> intentNames = intentManager.getExported(endpointProps);
+ List<Object> intents = intentManager.getIntents(intentNames);
Bus bus = BusFactory.newInstance().createBus();
if (contextRoot != null) {
httpServiceManager.registerServlet(bus, contextRoot, callingContext, sid);
@@ -139,15 +147,42 @@
JAXRSServerFactoryBean factory = createServerFactory(callingContext, endpointProps,
iClass, serviceBean, address, bus);
- intentManager.applyIntents(factory, intents, new ProviderIntentHandler());
+ applyIntents(intents, factory);
String completeEndpointAddress = httpServiceManager.getAbsoluteAddress(contextRoot, address);
EndpointDescription epd = createEndpointDesc(endpointProps, //
new String[] {RsConstants.RS_CONFIG_TYPE},
completeEndpointAddress,
- intents);
+ intentNames);
return createServerFromFactory(factory, epd);
}
+ private void applyIntents(List<Object> intents, AbstractJAXRSFactoryBean factory) {
+ List<Feature> features = intentManager.getIntents(Feature.class, intents);
+ factory.setFeatures(features);
+ DataBinding dataBinding = intentManager.getIntent(DataBinding.class, intents);
+ if (dataBinding != null) {
+ factory.setDataBinding(dataBinding);
+ }
+ BindingConfiguration binding = intentManager.getIntent(BindingConfiguration.class, intents);
+ if (binding != null) {
+ factory.setBindingConfig(binding);
+ }
+
+ List<Object> providers = new ArrayList<Object>();
+ for (Object intent : intents) {
+ if (isProvider(intent)) {
+ providers.add(intent);
+ }
+ }
+ factory.setProviders(providers);
+ }
+
+ private boolean isProvider(Object intent) {
+ return (intent instanceof ExceptionMapper) //
+ || (intent instanceof MessageBodyReader) //
+ || (intent instanceof MessageBodyWriter);
+ }
+
private boolean configTypeSupported(Map<String, Object> endpointProps, String configType) {
Collection<String> configs = getMultiValueProperty(endpointProps.get(RemoteConstants.SERVICE_EXPORTED_CONFIGS));
return configs == null || configs.isEmpty() || configs.contains(configType);
diff --git a/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/provider/RsProviderCustomTest.java b/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/provider/RsProviderCustomTest.java
index e28e108..02e93cf 100644
--- a/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/provider/RsProviderCustomTest.java
+++ b/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/provider/RsProviderCustomTest.java
@@ -18,17 +18,16 @@
*/
package org.apache.cxf.dosgi.dsw.handlers.rest.provider;
-import java.io.IOException;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Callable;
import org.apache.aries.rsa.spi.Endpoint;
import org.apache.cxf.dosgi.common.httpservice.HttpServiceManager;
-import org.apache.cxf.dosgi.common.intent.IntentProvider;
import org.apache.cxf.dosgi.common.intent.impl.IntentManagerImpl;
import org.apache.cxf.dosgi.dsw.handlers.rest.RsConstants;
import org.apache.cxf.dosgi.dsw.handlers.rest.RsProvider;
@@ -43,14 +42,15 @@
public class RsProviderCustomTest {
@Test
- public void testCustomProvider() throws IOException {
+ public void testCustomProvider() throws Exception {
RsProvider rsProvider = new RsProvider();
HttpServiceManager httpServiceManager = new HttpServiceManager();
Dictionary<String, Object> config = new Hashtable<>();
httpServiceManager.initFromConfig(config);
rsProvider.setHttpServiceManager(httpServiceManager);
IntentManagerImpl intentManager = new IntentManagerImpl();
- addIntent(intentManager, "my", MyWriter.class, MyReader.class);
+ addIntent(intentManager, "my", new MyWriter(), new MyReader());
+
rsProvider.setIntentManager(intentManager);
TaskServiceImpl taskService = new TaskServiceImpl();
BundleContext callingContext = EasyMock.createMock(BundleContext.class);
@@ -61,34 +61,32 @@
props.put(RsConstants.RS_ADDRESS_PROPERTY, serviceAddress);
props.put(RemoteConstants.SERVICE_EXPORTED_INTENTS, "my");
Class<?>[] ifaces = new Class[]{TaskService.class};
- Endpoint endpoint = rsProvider.exportService(taskService,
- callingContext,
- props,
- ifaces);
- Assert.assertEquals(serviceAddress, endpoint.description().getId());
- Assert.assertEquals("my", endpoint.description().getIntents().iterator().next());
-
- List<Object> providers = Arrays.asList((Object)MyReader.class);
- Task task1 = WebClient.create(serviceAddress, providers).path("/task").get(Task.class);
- Assert.assertEquals("test", task1.getName());
-
- TaskService proxy = (TaskService)rsProvider.importEndpoint(TaskService.class.getClassLoader(),
- callingContext, ifaces, endpoint.description());
- Task task = proxy.getTask();
- Assert.assertEquals("test", task.getName());
- endpoint.close();
+ try (Endpoint endpoint = rsProvider.exportService(taskService, callingContext, props, ifaces)) {
+ Assert.assertEquals(serviceAddress, endpoint.description().getId());
+ Assert.assertEquals("my", endpoint.description().getIntents().iterator().next());
+
+ List<Object> providers = Arrays.asList((Object)MyReader.class);
+ Task task1 = WebClient.create(serviceAddress, providers).path("/task").get(Task.class);
+ Assert.assertEquals("test", task1.getName());
+
+ TaskService proxy = (TaskService)rsProvider.importEndpoint(TaskService.class.getClassLoader(),
+ callingContext, ifaces,
+ endpoint.description());
+ Task task = proxy.getTask();
+ Assert.assertEquals("test", task.getName());
+ }
}
private void addIntent(IntentManagerImpl intentManager, String name, Object ... intents) {
- IntentProvider provider = intentProvider(intents);
+ Callable<List<Object>> provider = intentProvider(intents);
intentManager.addIntent(provider, name);
}
- private IntentProvider intentProvider(final Object ... intents) {
- return new IntentProvider() {
+ private Callable<List<Object>> intentProvider(final Object ... intents) {
+ return new Callable<List<Object>>() {
@Override
- public List<Object> getIntents() {
+ public List<Object> call() throws Exception {
return Arrays.asList(intents);
}
};
diff --git a/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/simple/RsProviderTest.java b/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/simple/RsProviderTest.java
index d082242..adc3df6 100644
--- a/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/simple/RsProviderTest.java
+++ b/provider-rs/src/test/java/org/apache/cxf/dosgi/dsw/handlers/rest/simple/RsProviderTest.java
@@ -55,11 +55,11 @@
String serviceAddress = "http://localhost:9181/";
props.put(RsConstants.RS_ADDRESS_PROPERTY, serviceAddress);
Class<?>[] ifaces = new Class[]{TaskService.class};
- Endpoint endpoint = rsProvider.exportService(taskService,
- callingContext,
- props,
- ifaces);
- try {
+
+ try (Endpoint endpoint = rsProvider.exportService(taskService,
+ callingContext,
+ props,
+ ifaces)) {
Assert.assertEquals(serviceAddress, endpoint.description().getId());
Task task1 = WebClient.create(serviceAddress).path("/task").get(Task.class);
@@ -69,8 +69,6 @@
callingContext, ifaces, endpoint.description());
Task task = proxy.getTask();
Assert.assertEquals("test", task.getName());
- } finally {
- endpoint.close();
}
}
diff --git a/provider-ws/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ws/WsProvider.java b/provider-ws/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ws/WsProvider.java
index 74649ad..9f0d873 100644
--- a/provider-ws/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ws/WsProvider.java
+++ b/provider-ws/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ws/WsProvider.java
@@ -23,6 +23,7 @@
import static org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_INTENTS_SUPPORTED;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -34,6 +35,7 @@
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.aegis.databinding.AegisDatabinding;
+import org.apache.cxf.binding.BindingConfiguration;
import org.apache.cxf.binding.soap.SoapBindingConfiguration;
import org.apache.cxf.databinding.DataBinding;
import org.apache.cxf.dosgi.common.httpservice.HttpServiceManager;
@@ -43,6 +45,7 @@
import org.apache.cxf.dosgi.common.util.ServerEndpoint;
import org.apache.cxf.endpoint.AbstractEndpointFactory;
import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.feature.Feature;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
import org.apache.cxf.frontend.ServerFactoryBean;
import org.apache.cxf.jaxb.JAXBDataBinding;
@@ -105,17 +108,28 @@
factory.setAddress(address);
addContextProperties(factory.getClientFactoryBean(), sd, WsConstants.WS_CONTEXT_PROPS_PROP_KEY);
WsdlSupport.setWsdlProperties(factory.getClientFactoryBean(), bundleContext, sd);
-
- Set<String> intents = intentManager.getImported(sd);
- intentManager.assertAllIntentsSupported(intents);
- intentManager.applyIntents(factory.getClientFactoryBean(), intents);
-
+ applyIntents(sd, factory);
return ProxyFactory.create(factory.create(), iClass);
} catch (Exception e) {
throw new RuntimeException("proxy creation failed", e);
}
}
+ private void applyIntents(Map<String, Object> sd, ClientProxyFactoryBean factory) {
+ Set<String> intentNames = intentManager.getImported(sd);
+ List<Object> intents = intentManager.getIntents(intentNames);
+ List<Feature> features = intentManager.getIntents(Feature.class, intents);
+ factory.setFeatures(features);
+ DataBinding dataBinding = intentManager.getIntent(DataBinding.class, intents);
+ if (dataBinding != null) {
+ factory.setDataBinding(dataBinding);
+ }
+ BindingConfiguration binding = intentManager.getIntent(BindingConfiguration.class, intents);
+ if (binding != null) {
+ factory.setBindingConfig(binding);
+ }
+ }
+
@SuppressWarnings("rawtypes")
public Endpoint exportService(Object serviceO,
BundleContext serviceContext,
@@ -141,6 +155,7 @@
factory.setAddress(address);
addContextProperties(factory, endpointProps, WsConstants.WS_CONTEXT_PROPS_PROP_KEY);
WsdlSupport.setWsdlProperties(factory, serviceContext, endpointProps);
+ applyIntents(endpointProps, factory);
intentManager.applyIntents(factory, intents);
String completeEndpointAddress = httpServiceManager.getAbsoluteAddress(contextRoot, address);
@@ -153,6 +168,21 @@
throw new RuntimeException("Error exporting service with adress " + completeEndpointAddress, e);
}
}
+
+ private void applyIntents(Map<String, Object> sd, AbstractEndpointFactory factory) {
+ Set<String> intentNames = intentManager.getExported(sd);
+ List<Object> intents = intentManager.getIntents(intentNames);
+ List<Feature> features = intentManager.getIntents(Feature.class, intents);
+ factory.setFeatures(features);
+ DataBinding dataBinding = intentManager.getIntent(DataBinding.class, intents);
+ if (dataBinding != null) {
+ factory.setDataBinding(dataBinding);
+ }
+ BindingConfiguration binding = intentManager.getIntent(BindingConfiguration.class, intents);
+ if (binding != null) {
+ factory.setBindingConfig(binding);
+ }
+ }
private boolean configTypeSupported(Map<String, Object> endpointProps, String configType) {
Collection<String> configs = getMultiValueProperty(endpointProps.get(RemoteConstants.SERVICE_EXPORTED_CONFIGS));
diff --git a/provider-ws/src/test/java/org/apache/cxf/dosgi/dsw/handlers/ws/PojoConfigurationTypeHandlerTest.java b/provider-ws/src/test/java/org/apache/cxf/dosgi/dsw/handlers/ws/PojoConfigurationTypeHandlerTest.java
index 538fbbf..b4b2f57 100644
--- a/provider-ws/src/test/java/org/apache/cxf/dosgi/dsw/handlers/ws/PojoConfigurationTypeHandlerTest.java
+++ b/provider-ws/src/test/java/org/apache/cxf/dosgi/dsw/handlers/ws/PojoConfigurationTypeHandlerTest.java
@@ -36,6 +36,7 @@
import org.apache.cxf.dosgi.dsw.handlers.simple.MySimpleEchoService;
import org.apache.cxf.endpoint.EndpointImpl;
import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.frontend.ClientFactoryBean;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
import org.apache.cxf.frontend.ServerFactoryBean;
import org.apache.cxf.jaxws.support.JaxWsEndpointImpl;
@@ -102,6 +103,8 @@
final ClientProxyFactoryBean cpfb = c.createMock(ClientProxyFactoryBean.class);
ReflectionServiceFactoryBean sf = c.createMock(ReflectionServiceFactoryBean.class);
EasyMock.expect(cpfb.getServiceFactory()).andReturn(sf).anyTimes();
+ ClientFactoryBean cf = c.createMock(ClientFactoryBean.class);
+ EasyMock.expect(cpfb.getClientFactoryBean()).andReturn(cf).anyTimes();
IntentManager intentManager = new IntentManagerImpl();
WsProvider p = new WsProvider() {
@Override
diff --git a/samples/ssl/README.md b/samples/ssl/README.md
new file mode 100644
index 0000000..e6eea83
--- /dev/null
+++ b/samples/ssl/README.md
@@ -0,0 +1,40 @@
+# CXF DOSGi ssl example
+
+This example demonstrates how to configure ssl with a custom keystore and required key based client auth using a plain DOSGi service with a custom intent.
+
+## Karaf SSL config
+
+We want the karaf HttpService to be secured by https and require a client certificate for authentication.
+
+
+ mkdir -p etc/keystores
+ # Create server key
+ keytool -genkey -dname CN=localhost -keyalg RSA -validity 100000 -alias serverkey -keypass password -storepass password -keystore etc/keystores/keystore.jks
+ # Create client key and add to keystore as trusted
+ keytool -genkey -dname CN=chris -keyalg RSA -validity 100000 -alias clientkey -keypass password -storepass password -keystore etc/keystores/client.jks
+ keytool -export -rfc -keystore etc/keystores/client.jks -storepass password -alias clientkey -file client.cer
+ keytool -import -trustcacerts -keystore etc/keystores/keystore.jks -storepass password -alias clientkey -file client.cer
+ # Export client cert as pkcs12 for browser
+ keytool -importkeystore -srckeystore etc/keystores/client.jks -destkeystore etc/keystores/client.p12 -deststoretype PKCS12
+
+ # Export server cert
+ keytool -exportcert -storepass password -keystore etc/keystores/keystore.jks -alias serverKey -file server.cert
+ # Import server cert into client store
+ keytool -importcert -storepass password -keystore etc/keystores/client.jks -alias serverKey -file server.cert
+
+
+- Copy the file org.ops4j.pax.web.cfg to the karaf etc dir.
+- Copy the keystores (*.jks) into the karaf etc directory.
+
+## Installation
+
+- Copy the server side ssl config org.apache.cxf.http.jetty-ssl.cfg into etc
+- Install the CXF DOSGi features
+- Install the example
+feature:repo-add cxf-dosgi 2.0-SNAPSHOT
+feature:install cxf-dosgi-provider-ws
+
+install -s mvn:org.apache.cxf.dosgi.samples/cxf-dosgi-ri-samples-ssl-interface/2.0_SNAPSHOT
+install -s mvn:org.apache.cxf.dosgi.samples/cxf-dosgi-ri-samples-ssl-impl/2.0-SNAPSHOT
+
+install -s mvn:org.apache.cxf.dosgi.samples/cxf-dosgi-ri-samples-ssl-client/2.0-SNAPSHOT
diff --git a/samples/ssl/client/pom.xml b/samples/ssl/client/pom.xml
new file mode 100644
index 0000000..00f29af
--- /dev/null
+++ b/samples/ssl/client/pom.xml
@@ -0,0 +1,46 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cxf-dosgi-ri-samples-ssl-client</artifactId>
+ <packaging>bundle</packaging>
+ <name>Distributed OSGI Greeter Bundle Client</name>
+
+ <parent>
+ <groupId>org.apache.cxf.dosgi.samples</groupId>
+ <artifactId>cxf-dosgi-ri-samples-ssl-parent</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <properties>
+ <topDirectoryLocation>../../..</topDirectoryLocation>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cxf.dosgi.samples</groupId>
+ <artifactId>cxf-dosgi-ri-samples-ssl-interface</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/samples/ssl/client/src/main/java/org/apache/cxf/dosgi/samples/ssl/client/EchoClient.java b/samples/ssl/client/src/main/java/org/apache/cxf/dosgi/samples/ssl/client/EchoClient.java
new file mode 100644
index 0000000..0b701e2
--- /dev/null
+++ b/samples/ssl/client/src/main/java/org/apache/cxf/dosgi/samples/ssl/client/EchoClient.java
@@ -0,0 +1,42 @@
+/**
+ * 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.samples.ssl.client;
+
+import org.apache.cxf.dosgi.samples.ssl.EchoService;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component//
+(//
+ immediate = true //
+)
+public class EchoClient {
+ private EchoService echoService;
+
+ @Activate
+ public void activate() {
+ System.out.println(echoService.echo("Hello"));
+ }
+
+ @Reference(target = "(service.imported=*)")
+ public void setEchoService(EchoService echoService) {
+ this.echoService = echoService;
+ }
+}
diff --git a/samples/ssl/impl/pom.xml b/samples/ssl/impl/pom.xml
new file mode 100644
index 0000000..5572b75
--- /dev/null
+++ b/samples/ssl/impl/pom.xml
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cxf-dosgi-ri-samples-ssl-impl</artifactId>
+ <packaging>bundle</packaging>
+ <name>Distributed OSGI Greeter Implementation Bundle</name>
+
+ <parent>
+ <groupId>org.apache.cxf.dosgi.samples</groupId>
+ <artifactId>cxf-dosgi-ri-samples-ssl-parent</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <properties>
+ <topDirectoryLocation>..</topDirectoryLocation>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cxf.dosgi.samples</groupId>
+ <artifactId>cxf-dosgi-ri-samples-ssl-interface</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/samples/ssl/impl/src/main/java/org/apache/cxf/dosgi/samples/ssl/impl/GreeterServiceImpl.java b/samples/ssl/impl/src/main/java/org/apache/cxf/dosgi/samples/ssl/impl/GreeterServiceImpl.java
new file mode 100644
index 0000000..ba56916
--- /dev/null
+++ b/samples/ssl/impl/src/main/java/org/apache/cxf/dosgi/samples/ssl/impl/GreeterServiceImpl.java
@@ -0,0 +1,42 @@
+/**
+ * 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.samples.ssl.impl;
+
+import org.apache.cxf.dosgi.samples.ssl.EchoService;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+
+@Component(//
+ immediate = true, //
+ property = //
+ {
+ "service.exported.interfaces=*", //
+ "service.exported.configs=org.apache.cxf.ws", //
+ "org.apache.cxf.ws.address=/echo", //
+ RemoteConstants.SERVICE_EXPORTED_INTENTS + "=ssl"
+ } //
+)
+public class GreeterServiceImpl implements EchoService {
+
+ @Override
+ public String echo(String msg) {
+ return msg;
+ }
+
+}
diff --git a/samples/ssl/interface/bnd.bnd b/samples/ssl/interface/bnd.bnd
new file mode 100644
index 0000000..a89d016
--- /dev/null
+++ b/samples/ssl/interface/bnd.bnd
@@ -0,0 +1 @@
+Export-Package: org.apache.cxf.dosgi.samples.ssl
\ No newline at end of file
diff --git a/samples/ssl/interface/pom.xml b/samples/ssl/interface/pom.xml
new file mode 100644
index 0000000..fa713c2
--- /dev/null
+++ b/samples/ssl/interface/pom.xml
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cxf-dosgi-ri-samples-ssl-interface</artifactId>
+ <packaging>bundle</packaging>
+ <name>Distributed OSGI Greeter Interface Bundle</name>
+
+ <parent>
+ <groupId>org.apache.cxf.dosgi.samples</groupId>
+ <artifactId>cxf-dosgi-ri-samples-ssl-parent</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <properties>
+ <topDirectoryLocation>..</topDirectoryLocation>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-http-jetty</artifactId>
+ <version>${cxf.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentProvider.java b/samples/ssl/interface/src/main/java/org/apache/cxf/dosgi/samples/ssl/EchoService.java
similarity index 79%
rename from common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentProvider.java
rename to samples/ssl/interface/src/main/java/org/apache/cxf/dosgi/samples/ssl/EchoService.java
index 10a970a..6669f24 100644
--- a/common/src/main/java/org/apache/cxf/dosgi/common/intent/IntentProvider.java
+++ b/samples/ssl/interface/src/main/java/org/apache/cxf/dosgi/samples/ssl/EchoService.java
@@ -16,13 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.cxf.dosgi.common.intent;
+package org.apache.cxf.dosgi.samples.ssl;
-import java.util.List;
-
-/**
- * Allows to provide a list of intents under one name
- */
-public interface IntentProvider {
- List<Object> getIntents();
+public interface EchoService {
+ String echo(String msg);
}
diff --git a/samples/ssl/interface/src/main/java/org/apache/cxf/dosgi/samples/ssl/SslIntent.java b/samples/ssl/interface/src/main/java/org/apache/cxf/dosgi/samples/ssl/SslIntent.java
new file mode 100644
index 0000000..c20fc20
--- /dev/null
+++ b/samples/ssl/interface/src/main/java/org/apache/cxf/dosgi/samples/ssl/SslIntent.java
@@ -0,0 +1,94 @@
+/**
+ * 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.samples.ssl;
+
+import static javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm;
+
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.transport.http.HttpConduitConfig;
+import org.apache.cxf.transport.http.HttpConduitFeature;
+import org.osgi.service.component.annotations.Component;
+
+@Component //
+(//
+ property = "org.apache.cxf.dosgi.IntentName=ssl" //
+)
+public class SslIntent implements Callable<List<Object>> {
+
+ private static final String CLIENT_PASSWORD = "password";
+
+ @Override
+ public List<Object> call() throws Exception {
+ HttpConduitFeature conduitFeature = new HttpConduitFeature();
+ HttpConduitConfig conduitConfig = new HttpConduitConfig();
+ TLSClientParameters tls = new TLSClientParameters();
+ String karafHome = System.getProperty("karaf.home");
+ tls.setKeyManagers(keyManager(keystore(karafHome + "/etc/keystores/client.jks", CLIENT_PASSWORD),
+ CLIENT_PASSWORD));
+ tls.setTrustManagers(trustManager(keystore(karafHome + "/etc/keystores/client.jks", CLIENT_PASSWORD)));
+ //tls.setTrustManagers(new TrustManager[]{new DefaultTrustManager()});
+ HostnameVerifier verifier = new HostnameVerifier() {
+
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ };
+ tls.setHostnameVerifier(verifier);
+ tls.setCertAlias("clientkey");
+ tls.setDisableCNCheck(true);
+ conduitConfig.setTlsClientParameters(tls);
+ conduitFeature.setConduitConfig(conduitConfig);
+
+ return Arrays.asList((Object)conduitFeature);
+ }
+
+ private TrustManager[] trustManager(KeyStore ks) throws Exception {
+ TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ factory.init(ks);
+ return factory.getTrustManagers();
+ }
+
+ private KeyManager[] keyManager(KeyStore ks, String keyPassword) throws Exception {
+ KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(getDefaultAlgorithm());
+ kmfactory.init(ks, keyPassword.toCharArray());
+ return kmfactory.getKeyManagers();
+ }
+
+ private KeyStore keystore(String keystorePath, String storePassword) throws Exception {
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(new FileInputStream(keystorePath), storePassword.toCharArray());
+ return ks;
+ }
+
+
+}
diff --git a/samples/ssl/keystores/client.jks b/samples/ssl/keystores/client.jks
new file mode 100644
index 0000000..9e0f0d2
--- /dev/null
+++ b/samples/ssl/keystores/client.jks
Binary files differ
diff --git a/samples/ssl/keystores/client.p12 b/samples/ssl/keystores/client.p12
new file mode 100644
index 0000000..2b32090
--- /dev/null
+++ b/samples/ssl/keystores/client.p12
Binary files differ
diff --git a/samples/ssl/keystores/keystore.jks b/samples/ssl/keystores/keystore.jks
new file mode 100644
index 0000000..12425aa
--- /dev/null
+++ b/samples/ssl/keystores/keystore.jks
Binary files differ
diff --git a/samples/ssl/org.ops4j.pax.web.cfg b/samples/ssl/org.ops4j.pax.web.cfg
new file mode 100644
index 0000000..c0a83cc
--- /dev/null
+++ b/samples/ssl/org.ops4j.pax.web.cfg
@@ -0,0 +1,11 @@
+javax.servlet.context.tempdir = ${karaf.home}/data/pax-web-jsp
+org.ops4j.pax.web.config.file = ${karaf.home}/etc/jetty.xml
+org.osgi.service.http.port = 8181
+org.osgi.service.http.secure.enabled=true
+org.ops4j.pax.web.ssl.keystore=etc/keystores/keystore.jks
+org.ops4j.pax.web.ssl.truststore=etc/keystores/keystore.jks
+org.ops4j.pax.web.ssl.password=password
+org.ops4j.pax.web.ssl.keypassword=password
+org.osgi.service.http.port.secure=8443
+org.ops4j.pax.web.ssl.clientauthneeded=true
+
diff --git a/samples/ssl/pom.xml b/samples/ssl/pom.xml
new file mode 100644
index 0000000..66a1d29
--- /dev/null
+++ b/samples/ssl/pom.xml
@@ -0,0 +1,54 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.cxf.dosgi.samples</groupId>
+ <artifactId>cxf-dosgi-ri-samples-ssl-parent</artifactId>
+ <packaging>pom</packaging>
+ <name>Distributed OSGI Greeter Bundles</name>
+
+ <parent>
+ <groupId>org.apache.cxf.dosgi</groupId>
+ <artifactId>cxf-dosgi-ri-parent</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <relativePath>../../parent/pom.xml</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <modules>
+ <module>interface</module>
+ <module>impl</module>
+ <module>client</module>
+ </modules>
+
+</project>