aries-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From csie...@apache.org
Subject [7/8] aries-jax-rs-whiteboard git commit: Handle extension errors
Date Fri, 25 Aug 2017 15:25:48 GMT
Handle extension errors

Also proper signalling of those errors


Project: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/repo
Commit: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/commit/08db7b15
Tree: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/tree/08db7b15
Diff: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/diff/08db7b15

Branch: refs/heads/master
Commit: 08db7b15ce4239e243bac3ed4766f505842d7ac3
Parents: 3b81013
Author: Carlos Sierra <csierra@apache.org>
Authored: Fri Aug 25 14:36:24 2017 +0200
Committer: Carlos Sierra <csierra@apache.org>
Committed: Fri Aug 25 14:36:24 2017 +0200

----------------------------------------------------------------------
 jax-rs.itests/src/main/java/test/JaxrsTest.java | 201 ++++++++++++++++++-
 .../internal/AriesJaxRSServiceRuntime.java      |  37 +++-
 .../internal/CXFJaxRsServiceRegistrator.java    |  45 ++++-
 .../aries/jax/rs/whiteboard/internal/Utils.java |  36 +---
 .../jax/rs/whiteboard/internal/Whiteboard.java  | 159 ++++++++++++---
 5 files changed, 401 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/08db7b15/jax-rs.itests/src/main/java/test/JaxrsTest.java
----------------------------------------------------------------------
diff --git a/jax-rs.itests/src/main/java/test/JaxrsTest.java b/jax-rs.itests/src/main/java/test/JaxrsTest.java
index 1ed4a6c..9857ae4 100644
--- a/jax-rs.itests/src/main/java/test/JaxrsTest.java
+++ b/jax-rs.itests/src/main/java/test/JaxrsTest.java
@@ -46,6 +46,7 @@ import test.types.TestHelper;
 
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.container.ContainerResponseFilter;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.Response;
 
@@ -870,21 +871,32 @@ public class JaxrsTest extends TestHelper {
     }
 
     @Test
-    public void testStandaloneFilter() {
+    public void testStandaloneFilter() throws InterruptedException {
         Client client = createClient();
 
         WebTarget webTarget = client.
             target("http://localhost:8080").
             path("test");
 
-        ServiceRegistration<?> filterRegistration = null;
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
 
         ServiceRegistration<?> serviceRegistration = null;
 
         try {
+            RuntimeDTO runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
             serviceRegistration = registerAddon(new TestAddon());
 
-            filterRegistration = registerExtension("Filter");
+            ServiceRegistration<?> filterRegistration = registerExtension(
+                "Filter");
+
+            runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                1, runtimeDTO.defaultApplication.extensionDTOs.length);
 
             Response response = webTarget.request().get();
 
@@ -893,13 +905,139 @@ public class JaxrsTest extends TestHelper {
                 response.readEntity(String.class));
 
             assertEquals("true", response.getHeaders().getFirst("Filtered"));
+
+            filterRegistration.unregister();
+
+            runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
         }
         finally {
             if (serviceRegistration != null) {
                 serviceRegistration.unregister();
             }
-            if (filterRegistration != null) {
-                filterRegistration.unregister();
+        }
+    }
+
+    @Test
+    public void testInvalidExtension() throws InterruptedException {
+        Client client = createClient();
+
+        WebTarget webTarget = client.
+            target("http://localhost:8080").
+            path("test");
+
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
+
+        ServiceRegistration<?> serviceRegistration = null;
+
+        try {
+            RuntimeDTO runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+            serviceRegistration = registerAddon(new TestAddon());
+
+            ServiceRegistration<?> filterRegistration =
+                registerInvalidExtension("Filter");
+
+            runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+            assertEquals(1, runtimeDTO.failedExtensionDTOs.length);
+            assertEquals(
+                (long)filterRegistration.getReference().getProperty(
+                    "service.id"),
+                runtimeDTO.failedExtensionDTOs[0].serviceId);
+            assertEquals(
+                DTOConstants.FAILURE_REASON_NOT_AN_EXTENSION_TYPE,
+                runtimeDTO.failedExtensionDTOs[0].failureReason);
+
+            Response response = webTarget.request().get();
+
+            assertEquals(
+                "This should say hello", "Hello test",
+                response.readEntity(String.class));
+
+            assertNull(response.getHeaders().getFirst("Filtered"));
+
+            filterRegistration.unregister();
+
+            runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+            assertEquals(0, runtimeDTO.failedExtensionDTOs.length);
+        }
+        finally {
+            if (serviceRegistration != null) {
+                serviceRegistration.unregister();
+            }
+        }
+    }
+
+    @Test
+    public void testUngettableExtension() throws InterruptedException {
+        Client client = createClient();
+
+        WebTarget webTarget = client.
+            target("http://localhost:8080").
+            path("test");
+
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
+
+        ServiceRegistration<?> serviceRegistration = null;
+
+        try {
+            RuntimeDTO runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+            serviceRegistration = registerAddon(new TestAddon());
+
+            ServiceRegistration<?> filterRegistration =
+                registerUngettableExtension("Filter");
+
+            runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+            assertEquals(1, runtimeDTO.failedExtensionDTOs.length);
+            assertEquals(
+                (long)filterRegistration.getReference().getProperty(
+                    "service.id"),
+                runtimeDTO.failedExtensionDTOs[0].serviceId);
+            assertEquals(
+                DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE,
+                runtimeDTO.failedExtensionDTOs[0].failureReason);
+
+            Response response = webTarget.request().get();
+
+            assertEquals(
+                "This should say hello", "Hello test",
+                response.readEntity(String.class));
+
+            assertNull(response.getHeaders().getFirst("Filtered"));
+
+            filterRegistration.unregister();
+
+            runtimeDTO = runtime.getRuntimeDTO();
+
+            assertEquals(
+                0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+            assertEquals(0, runtimeDTO.failedExtensionDTOs.length);
+        }
+        finally {
+            if (serviceRegistration != null) {
+                serviceRegistration.unregister();
             }
         }
     }
@@ -1060,9 +1198,62 @@ public class JaxrsTest extends TestHelper {
         }
 
         return bundleContext.registerService(
+            ContainerResponseFilter.class, testFilter, properties);
+    }
+
+    private ServiceRegistration<?> registerInvalidExtension(
+        String name, Object... keyValues) {
+
+        TestFilter testFilter = new TestFilter();
+
+        Dictionary<String, Object> properties = new Hashtable<>();
+
+        properties.put(JAX_RS_EXTENSION, true);
+        properties.put(JAX_RS_NAME, name);
+
+        for (int i = 0; i < keyValues.length; i = i + 2) {
+            properties.put(keyValues[i].toString(), keyValues[i + 1]);
+        }
+
+        return bundleContext.registerService(
             Object.class, testFilter, properties);
     }
 
+    private ServiceRegistration<?> registerUngettableExtension(
+        String name, Object... keyValues) {
+
+        Dictionary<String, Object> properties = new Hashtable<>();
+
+        properties.put(JAX_RS_EXTENSION, true);
+        properties.put(JAX_RS_NAME, name);
+
+        for (int i = 0; i < keyValues.length; i = i + 2) {
+            properties.put(keyValues[i].toString(), keyValues[i + 1]);
+        }
+
+        return bundleContext.registerService(
+            ContainerResponseFilter.class,
+            new ServiceFactory<ContainerResponseFilter>() {
+                @Override
+                public ContainerResponseFilter getService(
+                    Bundle bundle,
+                    ServiceRegistration<ContainerResponseFilter>
+                        serviceRegistration) {
+
+                    return null;
+                }
+
+                @Override
+                public void ungetService(
+                    Bundle bundle,
+                    ServiceRegistration<ContainerResponseFilter>
+                        serviceRegistration,
+                    ContainerResponseFilter containerResponseFilter) {
+
+                }
+            }, properties);
+    }
+
     private ServiceRegistration<Application> registerUngettableApplication(
         Object... keyValues) {
 

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/08db7b15/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxRSServiceRuntime.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxRSServiceRuntime.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxRSServiceRuntime.java
index a098f82..2d2706e 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxRSServiceRuntime.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxRSServiceRuntime.java
@@ -69,12 +69,19 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime {
     private TreeSet<ServiceReference<?>> _ungettableExtensions = new TreeSet<>();
 
     private TreeSet<ServiceReference<?>> _dependentServices = new TreeSet<>();
+
+    private TreeSet<ServiceReference<?>> _invalidExtensions = new TreeSet<>();
+
     private Map<String, Object> _defaultApplicationProperties;
 
     public void addDependentService(ServiceReference<?> serviceReference) {
         _dependentServices.add(serviceReference);
     }
 
+    public void addInvalidExtension(ServiceReference<?> serviceReference) {
+        _invalidExtensions.add(serviceReference);
+    }
+
     public void clearDefaultApplication() {
         _defaultApplicationProperties = Collections.emptyMap();
     }
@@ -107,6 +114,10 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime
{
         _erroredApplications.remove(serviceReference);
     }
 
+    public void removeInvalidExtension(ServiceReference<?> serviceReference) {
+        _invalidExtensions.remove(serviceReference);
+    }
+
     public boolean removeNotGettableApplication(
         ServiceReference<Application> serviceReference) {
 
@@ -247,16 +258,23 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime
{
                 FailedResourceDTO[]::new
             );
 
-        runtimeDTO.failedExtensionDTOs = unreferenciableExtensionsDTOStream().map(
-            sr -> buildFailedExtensionDTO(
-                DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE, sr)
-        ).toArray(
-            FailedExtensionDTO[]::new
-        );
+        runtimeDTO.failedExtensionDTOs = Stream.concat(
+                unreferenciableExtensionsDTOStream(),
+                invalidExtensionsDTOStream()
+            ).toArray(
+                FailedExtensionDTO[]::new
+            );
 
         return runtimeDTO;
     }
 
+    private Stream<FailedExtensionDTO> invalidExtensionsDTOStream() {
+        return _invalidExtensions.stream().map(
+            sr -> buildFailedExtensionDTO(
+                DTOConstants.FAILURE_REASON_NOT_AN_EXTENSION_TYPE, sr)
+        );
+    }
+
     private Stream<FailedResourceDTO> dependentServiceStreamDTO() {
         return _dependentServices.stream().map(
             sr -> buildFailedResourceDTO(
@@ -282,8 +300,11 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime
{
         return failedExtensionDTO;
     }
 
-    private Stream<ServiceReference<?>> unreferenciableExtensionsDTOStream()
{
-        return _ungettableExtensions.stream();
+    private Stream<FailedExtensionDTO> unreferenciableExtensionsDTOStream() {
+        return _ungettableExtensions.stream().map(
+            sr -> buildFailedExtensionDTO(
+                DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE, sr)
+        );
     }
 
     private FailedResourceDTO buildFailedResourceDTO(

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/08db7b15/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java
index 50d51a7..e06a907 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java
@@ -18,11 +18,15 @@
 package org.apache.aries.jax.rs.whiteboard.internal;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.stream.Stream;
 
 import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
 
 import org.apache.aries.jax.rs.whiteboard.internal.Utils.ComparableResourceProvider;
+import org.apache.aries.jax.rs.whiteboard.internal.Utils.ServiceTuple;
 import org.apache.cxf.Bus;
 import org.apache.cxf.endpoint.Server;
 import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
@@ -33,13 +37,16 @@ import org.apache.cxf.jaxrs.model.OperationResourceInfo;
 import org.apache.cxf.jaxrs.provider.json.JSONProvider;
 import org.apache.cxf.jaxrs.utils.ResourceUtils;
 import org.apache.cxf.message.Message;
+import org.osgi.framework.ServiceReference;
+
+import static org.apache.aries.jax.rs.whiteboard.internal.Utils.canonicalize;
 
 public class CXFJaxRsServiceRegistrator {
 
     private volatile boolean _closed = false;
     private final Application _application;
     private final Bus _bus;
-    private final Collection<Object> _providers = new ArrayList<>();
+    private final Collection<ServiceTuple<?>> _providers = new ArrayList<>();
     private Server _server;
     private final Collection<ResourceProvider> _services = new ArrayList<>();
 
@@ -60,12 +67,12 @@ public class CXFJaxRsServiceRegistrator {
         rewire();
     }
 
-    public void addProvider(Utils.ServiceTuple<?> tuple) {
+    public void addProvider(ServiceTuple<?> tuple) {
         if (_closed) {
             return;
         }
 
-        _providers.add(tuple.getService());
+        _providers.add(tuple);
 
         rewire();
     }
@@ -92,12 +99,12 @@ public class CXFJaxRsServiceRegistrator {
         rewire();
     }
 
-    public void removeProvider(Utils.ServiceTuple<?> tuple) {
+    public void removeProvider(ServiceTuple<?> tuple) {
         if (_closed) {
             return;
         }
 
-        _providers.remove(tuple.getService());
+        _providers.remove(tuple);
 
         rewire();
     }
@@ -166,8 +173,32 @@ public class CXFJaxRsServiceRegistrator {
 
         jaxRsServerFactoryBean.setProvider(jsonProvider);
 
-        for (Object provider : _providers) {
-            jaxRsServerFactoryBean.setProvider(provider);
+        for (ServiceTuple<?> provider : _providers) {
+            jaxRsServerFactoryBean.setProvider(
+                (Feature) featureContext -> {
+                    ServiceReference<?> serviceReference =
+                        provider.getServiceReference();
+
+                    String[] interfaces = canonicalize(
+                        serviceReference.getProperty("objectClass"));
+
+                    Class[] classes = Arrays.stream(interfaces).flatMap(
+                        className -> {
+                            try {
+                                return Stream.of(Class.forName(className));
+                            }
+                            catch (ClassNotFoundException e) {
+                                return Stream.empty();
+                            }
+                        }
+                    ).toArray(
+                        Class[]::new
+                    );
+
+                    featureContext.register(provider.getService(), classes);
+
+                    return true;
+                });
         }
 
         for (ResourceProvider resourceProvider: _services) {

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/08db7b15/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
index 058c1a8..e013c14 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
@@ -48,6 +48,16 @@ import static org.apache.aries.osgi.functional.OSGi.register;
  */
 public class Utils {
 
+    public static String[] canonicalize(Object propertyValue) {
+        if (propertyValue == null) {
+            return new String[0];
+        }
+        if (propertyValue instanceof String[]) {
+            return (String[]) propertyValue;
+        }
+        return new String[]{propertyValue.toString()};
+    }
+
     public static String generateApplicationName(
         PropertyHolder propertyHolder) {
 
@@ -109,32 +119,6 @@ public class Utils {
         }
     }
 
-    public static OSGi<?> safeRegisterGeneric(
-        ServiceReference<?> serviceReference,
-        String applicationName,
-        CXFJaxRsServiceRegistrator registrator,
-        AriesJaxRSServiceRuntime runtime) {
-
-        if (isExtension(serviceReference)) {
-            return safeRegisterExtension(
-                serviceReference, applicationName, registrator, runtime);
-        }
-        else {
-            return safeRegisterEndpoint(
-                serviceReference, applicationName, registrator, runtime);
-        }
-    }
-
-    private static boolean isExtension(ServiceReference<?> serviceReference) {
-        Object extensionProperty = serviceReference.getProperty(
-            "osgi.jaxrs.extension");
-
-        return
-            (extensionProperty != null) &&
-            (extensionProperty instanceof Boolean) &&
-            ((boolean) extensionProperty);
-    }
-
     public static OSGi<?> safeRegisterExtension(
         ServiceReference<?> serviceReference, String applicationName,
         CXFJaxRsServiceRegistrator registrator,

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/08db7b15/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
index 5a586fc..02e1b73 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
@@ -35,29 +35,46 @@ import org.osgi.service.http.runtime.HttpServiceRuntime;
 import org.osgi.service.jaxrs.runtime.JaxRSServiceRuntime;
 
 import javax.servlet.Servlet;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.DynamicFeature;
 import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.ParamConverterProvider;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.WriterInterceptor;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 import static java.lang.String.format;
 import static org.apache.aries.jax.rs.whiteboard.internal.AriesJaxRSServiceRuntime.getApplicationName;
+import static org.apache.aries.jax.rs.whiteboard.internal.Utils.canonicalize;
 import static org.apache.aries.jax.rs.whiteboard.internal.Utils.deployRegistrator;
 import static org.apache.aries.jax.rs.whiteboard.internal.Utils.generateApplicationName;
 import static org.apache.aries.jax.rs.whiteboard.internal.Utils.getProperties;
 import static org.apache.aries.jax.rs.whiteboard.internal.Utils.highestPer;
 import static org.apache.aries.jax.rs.whiteboard.internal.Utils.onlyGettables;
-import static org.apache.aries.jax.rs.whiteboard.internal.Utils.safeRegisterGeneric;
+import static org.apache.aries.jax.rs.whiteboard.internal.Utils.safeRegisterEndpoint;
+import static org.apache.aries.jax.rs.whiteboard.internal.Utils.safeRegisterExtension;
 import static org.apache.aries.jax.rs.whiteboard.internal.Utils.service;
-import static org.apache.aries.osgi.functional.OSGi.NOOP;
 import static org.apache.aries.osgi.functional.OSGi.all;
 import static org.apache.aries.osgi.functional.OSGi.bundleContext;
 import static org.apache.aries.osgi.functional.OSGi.just;
+import static org.apache.aries.osgi.functional.OSGi.nothing;
+import static org.apache.aries.osgi.functional.OSGi.onClose;
 import static org.apache.aries.osgi.functional.OSGi.register;
 import static org.apache.aries.osgi.functional.OSGi.serviceReferences;
 import static org.osgi.service.http.runtime.HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT;
@@ -85,9 +102,24 @@ public class Whiteboard {
             ServiceTuple::getServiceReference).andThen(
                 sr -> getApplicationBase(sr::getProperty));
 
+    public static final Collection<String> SUPPORTED_EXTENSION_INTERFACES = new HashSet<>(
+        Arrays.asList(
+            ContainerRequestFilter.class.getName(),
+            ContainerResponseFilter.class.getName(),
+            ReaderInterceptor.class.getName(),
+            WriterInterceptor.class.getName(),
+            MessageBodyReader.class.getName(),
+            MessageBodyWriter.class.getName(),
+            ContextResolver.class.getName(),
+            ExceptionMapper.class.getName(),
+            ParamConverterProvider.class.getName(),
+            Feature.class.getName(),
+            DynamicFeature.class.getName()
+        ));
+
     public static final String DEFAULT_NAME = ".default";
 
-    public static OSGi<Void> createWhiteboard(Dictionary<String, ?> configuration)
{
+    public static OSGi<?> createWhiteboard(Dictionary<String, ?> configuration)
{
         AriesJaxRSServiceRuntime runtime = new AriesJaxRSServiceRuntime();
 
         Map<String, ?> configurationMap = Maps.from(configuration);
@@ -99,18 +131,27 @@ public class Whiteboard {
             just(new ServiceRegistrationChangeCounter(runtimeRegistration)).flatMap(counter
->
             just(runtimeRegistration.getReference()).flatMap(runtimeReference ->
                 all(
-                    countChanges(
+                    ignore(countChanges(
                         whiteboardApplications(
                             runtimeReference, runtime, configurationMap),
-                        counter),
-                    countChanges(
-                        whiteBoardApplicationSingletons(
+                        counter)),
+                    ignore(countChanges(
+                        whiteBoardApplicationResources(
                             bundleContext, runtimeReference,
                             defaultApplicationReference, runtime),
-                        counter)
+                        counter)),
+                    ignore(countChanges(
+                        whiteBoardApplicationExtensions(
+                            bundleContext, runtimeReference,
+                            defaultApplicationReference, runtime),
+                        counter))
             ))))));
     }
 
+    private static OSGi<Void> ignore(OSGi<?> program) {
+        return program.map(t -> { return null;});
+    }
+
     private static OSGi<Collection<String>> bestEffortCalculationOfEnpoints(Filter
filter) {
         Collection<String> endPoints = new ArrayList<>();
 
@@ -127,16 +168,6 @@ public class Whiteboard {
         );
     }
 
-    private static String[] canonicalize(Object propertyValue) {
-        if (propertyValue == null) {
-            return new String[0];
-        }
-        if (propertyValue instanceof String[]) {
-            return (String[]) propertyValue;
-        }
-        return new String[]{propertyValue.toString()};
-    }
-
     private static ExtensionManagerBus createBus(
         BundleContext bundleContext, Map<String, ?> configuration) {
 
@@ -232,7 +263,7 @@ public class Whiteboard {
         ApplicationReference applicationReference,
         AriesJaxRSServiceRuntime runtime, OSGi<?> program) {
 
-        String[] extensionDependencies = canonicalize(
+        String[] extensionDependencies = Utils.canonicalize(
             serviceReference.getProperty(JAX_RS_EXTENSION_SELECT));
 
         if (extensionDependencies.length > 0) {
@@ -273,34 +304,89 @@ public class Whiteboard {
         return program;
     }
 
-    private static OSGi<?> whiteBoardApplicationSingletons(
+    private static OSGi<?> whiteBoardApplicationResources(
         BundleContext bundleContext,
         ServiceReference<?> jaxRsRuntimeServiceReference,
         ApplicationReference defaultApplicationReference,
         AriesJaxRSServiceRuntime runtime) {
         return
-            serviceReferences(getApplicationSingletonsFilter()).
+            serviceReferences(getResourcesFilter()).
                 filter(new TargetFilter<>(jaxRsRuntimeServiceReference)).
-                flatMap(endpointReference ->
-            chooseApplication(endpointReference, defaultApplicationReference).
+                flatMap(resourceReference ->
+            chooseApplication(
+                resourceReference, just(defaultApplicationReference)).
                 flatMap(applicationReference ->
             waitForExtensionDependencies(
-                bundleContext, endpointReference, applicationReference, runtime,
-                safeRegisterGeneric(
-                    endpointReference,
+                bundleContext, resourceReference, applicationReference,
+                runtime,
+                safeRegisterEndpoint(
+                    resourceReference,
                     applicationReference.getApplicationName(),
                     applicationReference.getRegistrator(), runtime)
         )));
     }
 
+    private static OSGi<?> whiteBoardApplicationExtensions(
+        BundleContext bundleContext,
+        ServiceReference<?> jaxRsRuntimeServiceReference,
+        ApplicationReference defaultApplicationReference,
+        AriesJaxRSServiceRuntime runtime) {
+        return
+            onlySupportedInterfaces(
+                serviceReferences(getApplicationExtensionsFilter()).
+                    filter(new TargetFilter<>(jaxRsRuntimeServiceReference)),
+                runtime::addInvalidExtension, runtime::removeInvalidExtension).
+                    flatMap(endpointReference ->
+            chooseApplication(
+                    endpointReference,
+                    all(
+                        just(defaultApplicationReference),
+                        allApplicationReferences())).
+                flatMap(applicationReference ->
+            waitForExtensionDependencies(
+                bundleContext, endpointReference, applicationReference, runtime,
+            safeRegisterExtension(
+                endpointReference,
+                applicationReference.getApplicationName(),
+                applicationReference.getRegistrator(), runtime)
+        )));
+    }
+
+    private static OSGi<ServiceReference<Object>> onlySupportedInterfaces(
+        OSGi<ServiceReference<Object>> program,
+        Consumer<ServiceReference<?>> onInvalidAdded,
+        Consumer<ServiceReference<?>> onInvalidRemoved) {
+
+        return program.flatMap(sr -> {
+            if (signalsValidInterface(sr)) {
+                return just(sr);
+            }
+            else {
+                onInvalidAdded.accept(sr);
+                return
+                    onClose(() -> onInvalidRemoved.accept(sr)).then(nothing());
+            }
+        });
+    }
+
+    private static boolean signalsValidInterface(
+        ServiceReference<Object> serviceReference) {
+
+        String[] objectClasses = canonicalize(serviceReference.getProperty(
+            "objectClass"));
+
+        return Arrays.stream(objectClasses).
+            anyMatch(SUPPORTED_EXTENSION_INTERFACES::contains);
+    }
+
     private static OSGi<ApplicationReference> chooseApplication(
-        ServiceReference<?> serviceReference, ApplicationReference theDefault) {
+        ServiceReference<?> serviceReference, OSGi<ApplicationReference> theDefault)
{
 
         Object applicationSelectProperty = serviceReference.getProperty(
             JAX_RS_APPLICATION_SELECT);
 
         if (applicationSelectProperty == null) {
-            return just(theDefault);
+            return theDefault;
         }
 
         String applicationName = getApplicationName(
@@ -316,11 +402,22 @@ public class Whiteboard {
         ));
     }
 
-    private static String getApplicationSingletonsFilter() {
+    public static OSGi<ApplicationReference> allApplicationReferences() {
+        return
+            serviceReferences(CXFJaxRsServiceRegistrator.class).
+                flatMap(registratorReference ->
+            just(getApplicationName(registratorReference::getProperty)).
+                flatMap(applicationName ->
+            service(registratorReference).flatMap(registrator ->
+            just(new ApplicationReference(applicationName, registrator))
+        )));
+    }
+
+    private static String getApplicationExtensionsFilter() {
         return format(
-            "(&(!(objectClass=%s))(|%s%s))",
+            "(&(!(objectClass=%s))(%s=%s)%s)",
             ApplicationExtensionRegistration.class.getName(),
-            getExtensionsFilter(), getResourcesFilter());
+            JAX_RS_EXTENSION, true, getExtensionsFilter());
     }
 
     private static OSGi<?> whiteboardApplications(


Mime
View raw message