aries-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rotty3...@apache.org
Subject [1/2] aries-jax-rs-whiteboard git commit: multiple, configurable whiteboards
Date Sun, 02 Jul 2017 20:06:33 GMT
Repository: aries-jax-rs-whiteboard
Updated Branches:
  refs/heads/master 7a47410aa -> ba62d9220


multiple, configurable whiteboards

Signed-off-by: Raymond Augé <rotty3000@apache.org>


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/506532b3
Tree: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/tree/506532b3
Diff: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/diff/506532b3

Branch: refs/heads/master
Commit: 506532b3d500b1c50be9795c6945d8fec6145644
Parents: 7a47410
Author: Raymond Auge <rotty3000@apache.org>
Authored: Fri Jun 30 23:32:27 2017 -0400
Committer: Raymond Auge <rotty3000@apache.org>
Committed: Sun Jul 2 16:05:26 2017 -0400

----------------------------------------------------------------------
 .../main/java/test/WhiteboardFactoryTest.java   | 117 +++++++
 .../activator/CXFJaxRsBundleActivator.java      | 223 +++-----------
 .../internal/AriesJaxRSServiceRuntime.java      |  74 +++++
 .../internal/CXFJaxRsServiceRegistrator.java    |   1 -
 .../aries/jax/rs/whiteboard/internal/Maps.java  |  39 +++
 .../jax/rs/whiteboard/internal/Strings.java     |  44 +++
 .../jax/rs/whiteboard/internal/Whiteboard.java  | 305 +++++++++++++++++++
 .../internal/WhiteboardServiceFactory.java      |  66 ++++
 8 files changed, 689 insertions(+), 180 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/jax-rs.itests/src/main/java/test/WhiteboardFactoryTest.java
----------------------------------------------------------------------
diff --git a/jax-rs.itests/src/main/java/test/WhiteboardFactoryTest.java b/jax-rs.itests/src/main/java/test/WhiteboardFactoryTest.java
new file mode 100644
index 0000000..810dcc2
--- /dev/null
+++ b/jax-rs.itests/src/main/java/test/WhiteboardFactoryTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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 test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Hashtable;
+
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.jaxrs.runtime.JaxRSServiceRuntime;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class WhiteboardFactoryTest {
+
+    @Test
+    public void testDefaultDefaultWhiteboardConfig() throws Exception {
+        ServiceTracker<JaxRSServiceRuntime, JaxRSServiceRuntime> runtimeTracker =
+            new ServiceTracker<>(
+                bundleContext, JaxRSServiceRuntime.class, null);
+
+        try {
+            runtimeTracker.open();
+
+            JaxRSServiceRuntime runtime = runtimeTracker.waitForService(5000);
+
+            assertNotNull(runtime);
+
+            ServiceReference<JaxRSServiceRuntime> serviceReference = runtimeTracker.getServiceReference();
+
+            assertNotNull(serviceReference);
+
+            assertEquals(1, runtimeTracker.size());
+        }
+        finally {
+            runtimeTracker.close();
+        }
+    }
+
+    @Test
+    public void testCreateNewInstance() throws Exception {
+        ServiceTracker<ConfigurationAdmin, ConfigurationAdmin> configTracker =
+            new ServiceTracker<>(
+                bundleContext, ConfigurationAdmin.class, null);
+
+        ServiceTracker<JaxRSServiceRuntime, JaxRSServiceRuntime> runtimeTracker =
+            new ServiceTracker<>(
+                bundleContext, JaxRSServiceRuntime.class, null);
+
+        try {
+            configTracker.open();
+            runtimeTracker.open();
+
+            JaxRSServiceRuntime runtime = runtimeTracker.waitForService(5000);
+
+            assertNotNull(runtime);
+
+            ServiceReference<JaxRSServiceRuntime> serviceReference = runtimeTracker.getServiceReference();
+
+            assertNotNull(serviceReference);
+
+            assertEquals(1, runtimeTracker.size());
+
+            int trackingCount = runtimeTracker.getTrackingCount();
+
+            ConfigurationAdmin admin = configTracker.waitForService(5000);
+
+            Configuration configuration = admin.createFactoryConfiguration(
+                "org.apache.aries.jax.rs.whiteboard", "?");
+
+            configuration.update(new Hashtable<>());
+
+            do {
+                Thread.sleep(50);
+            }
+            while (runtimeTracker.getTrackingCount() <= trackingCount);
+
+            assertEquals(2, runtimeTracker.size());
+
+            configuration.delete();
+
+            do {
+                Thread.sleep(50);
+            }
+            while (runtimeTracker.getTrackingCount() <= trackingCount);
+
+            assertEquals(1, runtimeTracker.size());
+        }
+        finally {
+            runtimeTracker.close();
+            configTracker.close();
+        }
+    }
+
+    private BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java
index d2a9204..4fa17c8 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java
@@ -17,216 +17,81 @@
 
 package org.apache.aries.jax.rs.whiteboard.activator;
 
-import javax.servlet.Servlet;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.core.Application;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.Executors;
+
 import javax.ws.rs.ext.RuntimeDelegate;
 
-import org.apache.aries.jax.rs.whiteboard.internal.CXFJaxRsServiceRegistrator;
-import org.apache.aries.jax.rs.whiteboard.internal.ClientBuilderFactory;
-import org.apache.aries.jax.rs.whiteboard.internal.DefaultApplication;
-import org.apache.aries.jax.rs.whiteboard.internal.DefaultWeb;
-import org.apache.aries.osgi.functional.OSGi;
-import org.apache.aries.osgi.functional.OSGiResult;
-import org.apache.cxf.Bus;
-import org.apache.cxf.BusFactory;
-import org.apache.cxf.bus.CXFBusFactory;
-import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
+import org.apache.aries.jax.rs.whiteboard.internal.WhiteboardServiceFactory;
+import org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-
-import static java.lang.String.format;
-import static org.apache.aries.jax.rs.whiteboard.internal.Utils.*;
-import static org.apache.aries.osgi.functional.OSGi.just;
-import static org.apache.aries.osgi.functional.OSGi.serviceReferences;
-import static org.apache.aries.osgi.functional.OSGi.services;
-import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.*;
-import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME;
-import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT;
-import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME;
-import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN;
-import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_APPLICATION_SELECT;
-
 public class CXFJaxRsBundleActivator implements BundleActivator {
 
     private static final Logger _log = LoggerFactory.getLogger(CXFJaxRsBundleActivator.class);
 
-    private OSGiResult<?> _applicationsResult;
-    private OSGiResult<?> _applicationSingletonsResult;
-    private BundleContext _bundleContext;
-    private Bus _bus;
-    private ServiceRegistration<ClientBuilder> _clientBuilder;
-    private ServiceRegistration<DefaultWeb> _defaultWeb;
-    private OSGiResult<?> _extensionsResult;
-    private OSGiResult<?> _singletonsResult;
+    static {
+        RuntimeDelegate.setInstance(new RuntimeDelegateImpl());
+    }
+
+    private ServiceRegistration<ManagedServiceFactory> _serviceRegistration;
+    private WhiteboardServiceFactory _whiteboardServiceFactory;
+    private String _defaultName;
 
     @Override
     public void start(BundleContext bundleContext) throws Exception {
-        _bundleContext = bundleContext;
-
         if (_log.isDebugEnabled()) {
-            _log.debug("Beginning initialization");
+            _log.debug("Starting the whiteboard factory");
         }
 
-        initRuntimeDelegate(bundleContext);
-
-        // TODO make the context path of the JAX-RS Whiteboard configurable.
-        _bus = BusFactory.newInstance(
-            CXFBusFactory.class.getName()).createBus();
-        registerCXFServletService(_bus);
-
-        OSGi<?> applications =
-            repeatInOrder(
-                serviceReferences(Application.class, getApplicationFilter())).
-            flatMap(ref ->
-            just(
-                CXFJaxRsServiceRegistrator.getProperties(
-                    ref, JAX_RS_APPLICATION_BASE)).
-                flatMap(properties ->
-            service(ref).flatMap(application ->
-            cxfRegistrator(_bus, application, properties)
-        )));
-
-        _applicationsResult = applications.run(bundleContext);
-
-        OSGi<?> applicationSingletons =
-            serviceReferences(format("(%s=*)", JAX_RS_APPLICATION_SELECT)).
-                flatMap(ref ->
-            just(ref.getProperty(JAX_RS_APPLICATION_SELECT).toString()).
-                flatMap(applicationFilter ->
-            services(CXFJaxRsServiceRegistrator.class, applicationFilter).
-                flatMap(registrator ->
-            safeRegisterGeneric(ref, registrator)
-        )));
-
-        _applicationSingletonsResult = applicationSingletons.run(bundleContext);
-
-        Map<String, Object> properties = new HashMap<>();
-        properties.put(JAX_RS_APPLICATION_BASE, "/");
-        properties.put(JAX_RS_NAME, ".default");
-
-        CXFJaxRsServiceRegistrator defaultServiceRegistrator =
-            new CXFJaxRsServiceRegistrator(
-                _bus, new DefaultApplication(), properties);
-
-        OSGi<?> extensions =
-            serviceReferences(getExtensionFilter()).flatMap(ref ->
-            waitForExtensionDependencies(ref,
-                safeRegisterExtension(ref, defaultServiceRegistrator)
-            )
-        );
-
-        _extensionsResult = extensions.run(bundleContext);
-
-        OSGi<?> singletons =
-            serviceReferences(getSingletonsFilter()).
-                flatMap(serviceReference ->
-            waitForExtensionDependencies(serviceReference,
-                safeRegisterEndpoint(
-                    serviceReference, defaultServiceRegistrator)
-            )
-        );
-
-        _singletonsResult = singletons.run(bundleContext);
-
-        Dictionary<String, Object> dictionary = new Hashtable<>();
-        dictionary.put(JAX_RS_APPLICATION_SELECT, "(osgi.jaxrs.name=.default)");
-        dictionary.put(JAX_RS_RESOURCE, "true");
-        dictionary.put(Constants.SERVICE_RANKING, -1);
-
-        _defaultWeb =  _bundleContext.registerService(
-            DefaultWeb.class, new DefaultWeb(), dictionary);
-        _clientBuilder = _bundleContext.registerService(
-            ClientBuilder.class, new ClientBuilderFactory(), null);
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        _clientBuilder.unregister();
-        _defaultWeb.unregister();
-        _applicationsResult.close();
-        _applicationSingletonsResult.close();
-        _extensionsResult.close();
-        _singletonsResult.close();
-    }
+        _whiteboardServiceFactory = new WhiteboardServiceFactory(bundleContext);
 
-    private static String buildExtensionFilter(String filter) {
-        return String.format("(&%s%s)", getExtensionFilter(), filter);
-    }
+        _defaultName = _whiteboardServiceFactory.getName() + ".default";
 
-    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()};
-    }
+        Dictionary<String, Object> properties = new Hashtable<>();
+        properties.put(Constants.SERVICE_PID, _whiteboardServiceFactory.getName());
 
-    private static CXFNonSpringServlet createCXFServlet(Bus bus) {
-        CXFNonSpringServlet cxfNonSpringServlet = new CXFNonSpringServlet();
-        cxfNonSpringServlet.setBus(bus);
-        return cxfNonSpringServlet;
-    }
+        _serviceRegistration = bundleContext.registerService(
+            ManagedServiceFactory.class, _whiteboardServiceFactory, properties);
 
-    private static String getApplicationFilter() {
-        return format("(%s=*)", JAX_RS_APPLICATION_BASE);
-    }
+        if (_log.isDebugEnabled()) {
+            _log.debug("Whiteboard factory started");
+        }
 
-    private static String getExtensionFilter() {
-        return format("(%s=*)", JAX_RS_EXTENSION);
-    }
+        Executors.newSingleThreadExecutor().submit(() -> {
+            try {
+                Dictionary<String, Object> defaultConfiguration = new Hashtable<>();
 
-    private static String getSingletonsFilter() {
-        return format("(%s=true)", JAX_RS_RESOURCE);
-    }
+                defaultConfiguration.put(Constants.SERVICE_PID, _defaultName);
 
-    /**
-     * Initialize instance so it is never looked up again
-     * @param bundleContext
-     */
-    private void initRuntimeDelegate(BundleContext bundleContext) {
-        RuntimeDelegate.setInstance(new org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl());
+                _whiteboardServiceFactory.updated(_defaultName, defaultConfiguration);
+            } catch (ConfigurationException ce) {
+                _log.error("Configuration error", ce);
+            }
+        });
     }
 
-    private ServiceRegistration<Servlet> registerCXFServletService(Bus bus) {
-        Dictionary<String, Object> properties = new Hashtable<>();
-        properties.put(HTTP_WHITEBOARD_CONTEXT_SELECT,
-            format("(%s=%s)", HTTP_WHITEBOARD_CONTEXT_NAME,
-                HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME));
-        properties.put(HTTP_WHITEBOARD_SERVLET_PATTERN, "/*");
-        properties.put(Constants.SERVICE_RANKING, -1);
-        CXFNonSpringServlet cxfNonSpringServlet = createCXFServlet(bus);
-        return _bundleContext.registerService(
-            Servlet.class, cxfNonSpringServlet, properties);
-    }
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        if (_log.isDebugEnabled()) {
+            _log.debug("Stopping whiteboard factory");
+        }
 
-    private static OSGi<?> waitForExtensionDependencies(
-        ServiceReference<?> serviceReference, OSGi<?> program) {
+        _serviceRegistration.unregister();
 
-        String[] extensionDependencies = canonicalize(
-            serviceReference.getProperty(JAX_RS_EXTENSION_SELECT));
+        _whiteboardServiceFactory.deleted(_defaultName);
 
-        for (String extensionDependency : extensionDependencies) {
-            program =
-                serviceReferences(buildExtensionFilter(extensionDependency)).
-                then(program);
+        if (_log.isDebugEnabled()) {
+            _log.debug("Stopped whiteboard factory");
         }
-
-        return program;
     }
 
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/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
new file mode 100644
index 0000000..536cd23
--- /dev/null
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxRSServiceRuntime.java
@@ -0,0 +1,74 @@
+/*
+ * 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.aries.jax.rs.whiteboard.internal;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
+import org.osgi.service.jaxrs.runtime.JaxRSServiceRuntime;
+import org.osgi.service.jaxrs.runtime.dto.RequestInfoDTO;
+import org.osgi.service.jaxrs.runtime.dto.RuntimeDTO;
+
+public class AriesJaxRSServiceRuntime
+    extends HttpServlet implements JaxRSServiceRuntime {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Bus _bus;
+    private final CXFNonSpringServlet _cxfNonSpringServlet;
+
+    public AriesJaxRSServiceRuntime(Bus bus) {
+        _bus = bus;
+
+        CXFNonSpringServlet cxfNonSpringServlet = new CXFNonSpringServlet();
+        cxfNonSpringServlet.setBus(_bus);
+
+        _cxfNonSpringServlet = cxfNonSpringServlet;
+    }
+
+    @Override
+    public RequestInfoDTO calculateRequestInfoDTO(String path) {
+        return null;
+    }
+
+    @Override
+    public RuntimeDTO getRuntimeDTO() {
+        return null;
+    }
+
+    @Override
+    public void init(ServletConfig config) throws ServletException {
+        _cxfNonSpringServlet.init(config);
+    }
+
+    @Override
+    protected void service(
+            HttpServletRequest request, HttpServletResponse response)
+        throws ServletException, IOException {
+
+        _cxfNonSpringServlet.service(request, response);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/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 e89f6f6..43c9f1a 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
@@ -28,7 +28,6 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import javax.ws.rs.core.Application;
-import javax.ws.rs.ext.RuntimeDelegate;
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.endpoint.Server;

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Maps.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Maps.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Maps.java
new file mode 100644
index 0000000..a5f1b48
--- /dev/null
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Maps.java
@@ -0,0 +1,39 @@
+/*
+ * 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.aries.jax.rs.whiteboard.internal;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Maps {
+
+    public static <K, V> Map<K, V> from(Dictionary<K, V> dictionary) {
+        Map<K, V> map = new HashMap<>();
+
+        for (Enumeration<K> keys = dictionary.keys(); keys.hasMoreElements();) {
+            K k = keys.nextElement();
+
+            map.put(k, dictionary.get(k));
+        }
+
+        return map;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Strings.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Strings.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Strings.java
new file mode 100644
index 0000000..7fc2ac5
--- /dev/null
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Strings.java
@@ -0,0 +1,44 @@
+package org.apache.aries.jax.rs.whiteboard.internal;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+public class Strings {
+
+    @SuppressWarnings({"unchecked" })
+    public static Optional<List<String>> stringPlus(Object obj) {
+        if (obj == null) {
+            return Optional.empty();
+        }
+
+        List<String> strings = new ArrayList<>();
+
+        if (obj instanceof String) {
+            strings.add((String)obj);
+        }
+        else if (Collection.class.isInstance(obj) &&
+                (ParameterizedType.class.isAssignableFrom(obj.getClass())) &&
+                ((ParameterizedType)obj).getActualTypeArguments()[0].equals(String.class))
{
+
+            for (String item : (Collection<String>)obj) {
+                strings.add(item);
+            }
+        }
+        else if (obj.getClass().isArray() &&
+                String.class.isAssignableFrom(obj.getClass().getComponentType())) {
+
+            for (String item : (String[])obj) {
+                strings.add(item);
+            }
+        }
+        else {
+            return Optional.empty();
+        }
+
+        return Optional.of(strings);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/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
new file mode 100644
index 0000000..a15b07f
--- /dev/null
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
@@ -0,0 +1,305 @@
+/*
+ * 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.aries.jax.rs.whiteboard.internal;
+
+import static java.lang.String.format;
+import static org.apache.aries.jax.rs.whiteboard.internal.Utils.cxfRegistrator;
+import static org.apache.aries.jax.rs.whiteboard.internal.Utils.repeatInOrder;
+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.safeRegisterGeneric;
+import static org.apache.aries.jax.rs.whiteboard.internal.Utils.service;
+import static org.apache.aries.osgi.functional.OSGi.just;
+import static org.apache.aries.osgi.functional.OSGi.serviceReferences;
+import static org.apache.aries.osgi.functional.OSGi.services;
+import static org.osgi.service.http.runtime.HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT;
+import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME;
+import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT;
+import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME;
+import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN;
+import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET;
+import static org.osgi.service.jaxrs.runtime.JaxRSServiceRuntimeConstants.JAX_RS_SERVICE_ENDPOINT;
+import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_APPLICATION_BASE;
+import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_APPLICATION_SELECT;
+import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_EXTENSION;
+import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_EXTENSION_SELECT;
+import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_NAME;
+import static org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_RESOURCE;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.servlet.Servlet;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Application;
+
+import org.apache.aries.osgi.functional.OSGi;
+import org.apache.aries.osgi.functional.OSGiResult;
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.extension.ExtensionManagerBus;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.http.runtime.HttpServiceRuntime;
+import org.osgi.service.jaxrs.runtime.JaxRSServiceRuntime;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class Whiteboard implements AutoCloseable {
+
+    public Whiteboard(
+            BundleContext bundleContext, Map<String, Object> configuration)
+        throws ConfigurationException {
+
+        BundleWiring wiring = bundleContext.getBundle().adapt(BundleWiring.class);
+
+        configuration.put(_ID, configuration.get(Constants.SERVICE_PID));
+
+        ExtensionManagerBus bus = new ExtensionManagerBus(null, configuration, wiring.getClassLoader());
+
+        bus.initialize();
+
+        _runtimeRegistration = registerJaxRSServiceRuntime(bundleContext, bus, configuration);
+
+        OSGi<?> applications =
+            repeatInOrder(
+                serviceReferences(Application.class, getApplicationFilter())).
+            flatMap(ref ->
+            just(
+                CXFJaxRsServiceRegistrator.getProperties(
+                    ref, JAX_RS_APPLICATION_BASE)).
+                flatMap(properties ->
+            service(ref).flatMap(application ->
+            cxfRegistrator(bus, application, properties)
+        )));
+
+        _applicationsResult = applications.run(bundleContext);
+
+        OSGi<?> applicationSingletons =
+            serviceReferences(format("(%s=*)", JAX_RS_APPLICATION_SELECT)).
+                flatMap(ref ->
+            just(ref.getProperty(JAX_RS_APPLICATION_SELECT).toString()).
+                flatMap(applicationFilter ->
+            services(CXFJaxRsServiceRegistrator.class, applicationFilter).
+                flatMap(registrator ->
+            safeRegisterGeneric(ref, registrator)
+        )));
+
+        _applicationSingletonsResult = applicationSingletons.run(bundleContext);
+
+        Map<String, Object> properties = new HashMap<>();
+        properties.put(JAX_RS_APPLICATION_BASE, "/");
+        properties.put(JAX_RS_NAME, ".default");
+
+        CXFJaxRsServiceRegistrator defaultServiceRegistrator =
+            new CXFJaxRsServiceRegistrator(
+                bus, new DefaultApplication(), properties);
+
+        OSGi<?> extensions =
+            serviceReferences(getExtensionFilter()).flatMap(ref ->
+            waitForExtensionDependencies(ref,
+                safeRegisterExtension(ref, defaultServiceRegistrator)
+            )
+        );
+
+        _extensionsResult = extensions.run(bundleContext);
+
+        OSGi<?> singletons =
+            serviceReferences(getSingletonsFilter()).
+                flatMap(serviceReference ->
+            waitForExtensionDependencies(serviceReference,
+                safeRegisterEndpoint(
+                    serviceReference, defaultServiceRegistrator)
+            )
+        );
+
+        _singletonsResult = singletons.run(bundleContext);
+
+        Dictionary<String, Object> dictionary = new Hashtable<>();
+        dictionary.put(JAX_RS_APPLICATION_SELECT, "(osgi.jaxrs.name=.default)");
+        dictionary.put(JAX_RS_RESOURCE, "true");
+        dictionary.put(Constants.SERVICE_RANKING, -1);
+
+        _defaultWeb =  bundleContext.registerService(
+            DefaultWeb.class, new DefaultWeb(), dictionary);
+        _clientBuilder = bundleContext.registerService(
+            ClientBuilder.class, new ClientBuilderFactory(), null);
+    }
+
+    @Override
+    public void close() {
+        _clientBuilder.unregister();
+        _defaultWeb.unregister();
+        _applicationsResult.close();
+        _applicationSingletonsResult.close();
+        _extensionsResult.close();
+        _singletonsResult.close();
+        _runtimeRegistration.unregister();
+    }
+
+    private void bestEffortCalculationOfEnpoints(
+            Dictionary<String, Object> properties, BundleContext bundleContext)
+        throws ConfigurationException {
+
+        String targetFilter = (String)properties.get(HTTP_WHITEBOARD_TARGET);
+
+        Filter filter;
+
+        try {
+            filter = bundleContext.createFilter(format(
+                "(&(objectClass=%s)%s)",
+                HttpServiceRuntime.class.getName(),
+                targetFilter));
+        }
+        catch (InvalidSyntaxException ise) {
+            throw new ConfigurationException(
+                HTTP_WHITEBOARD_TARGET, format("Invalid syntax for filter {}", targetFilter));
+        }
+
+        ServiceTracker<HttpServiceRuntime, HttpServiceRuntime> httpRuntimeTracker =
+            new ServiceTracker<>(bundleContext, filter, null);
+
+        httpRuntimeTracker.open();
+
+        try {
+            httpRuntimeTracker.waitForService(1000);
+        }
+        catch (InterruptedException ie) {
+        }
+
+        Optional.ofNullable(
+            httpRuntimeTracker.getServiceReferences()
+        ).ifPresent(
+            array -> {
+                Collection<String> endPoints = new ArrayList<>();
+
+                Arrays.stream(array).forEach(
+                    reference -> Strings.stringPlus(
+                        reference.getProperty(HTTP_SERVICE_ENDPOINT)
+                    ).ifPresent(
+                        values -> values.stream().forEach(
+                            value -> {
+                                endPoints.add(value);
+                            }
+                        )
+                    )
+                );
+
+                properties.put(JAX_RS_SERVICE_ENDPOINT, endPoints);
+            }
+        );
+    }
+
+    private static String buildExtensionFilter(String filter) {
+        return String.format("(&%s%s)", getExtensionFilter(), filter);
+    }
+
+    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 String getApplicationFilter() {
+        return format("(%s=*)", JAX_RS_APPLICATION_BASE);
+    }
+
+    private static String getExtensionFilter() {
+        return format("(%s=*)", JAX_RS_EXTENSION);
+    }
+
+    private static String getSingletonsFilter() {
+        return format("(%s=true)", JAX_RS_RESOURCE);
+    }
+
+    private ServiceRegistration<?> registerJaxRSServiceRuntime(
+            BundleContext bundleContext, Bus bus, Map<String, Object> configuration)
+        throws ConfigurationException {
+
+        Dictionary<String, Object> properties = new Hashtable<>(configuration);
+
+        properties.put(
+            HTTP_WHITEBOARD_TARGET,
+            configuration.computeIfAbsent(
+                HTTP_WHITEBOARD_TARGET,
+                k -> "(osgi.http.endpoint=*)"));
+
+        properties.put(
+            HTTP_WHITEBOARD_CONTEXT_SELECT,
+            configuration.computeIfAbsent(
+                HTTP_WHITEBOARD_CONTEXT_SELECT,
+                    k -> format(
+                        "(%s=%s)",
+                        HTTP_WHITEBOARD_CONTEXT_NAME,
+                        HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME)));
+
+        properties.put(
+            HTTP_WHITEBOARD_SERVLET_PATTERN,
+            configuration.computeIfAbsent(
+                HTTP_WHITEBOARD_SERVLET_PATTERN,
+                k -> "/*"));
+
+        properties.put(Constants.SERVICE_RANKING, -1);
+
+        bestEffortCalculationOfEnpoints(properties, bundleContext);
+
+        return bundleContext.registerService(
+            new String[] {JaxRSServiceRuntime.class.getName(), Servlet.class.getName()},
+            new AriesJaxRSServiceRuntime(bus), properties);
+    }
+
+    private static OSGi<?> waitForExtensionDependencies(
+        ServiceReference<?> serviceReference, OSGi<?> program) {
+
+        String[] extensionDependencies = canonicalize(
+            serviceReference.getProperty(JAX_RS_EXTENSION_SELECT));
+
+        for (String extensionDependency : extensionDependencies) {
+            program =
+                serviceReferences(buildExtensionFilter(extensionDependency)).
+                then(program);
+        }
+
+        return program;
+    }
+
+    private static final String _ID = "org.apache.cxf.bus.id";
+
+    private final OSGiResult<?> _applicationsResult;
+    private final OSGiResult<?> _applicationSingletonsResult;
+    private final ServiceRegistration<ClientBuilder> _clientBuilder;
+    private final ServiceRegistration<DefaultWeb> _defaultWeb;
+    private final OSGiResult<?> _extensionsResult;
+    private final ServiceRegistration<?> _runtimeRegistration;
+    private final OSGiResult<?> _singletonsResult;
+
+}

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/506532b3/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/WhiteboardServiceFactory.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/WhiteboardServiceFactory.java
b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/WhiteboardServiceFactory.java
new file mode 100644
index 0000000..8b41700
--- /dev/null
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/WhiteboardServiceFactory.java
@@ -0,0 +1,66 @@
+/*
+ * 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.aries.jax.rs.whiteboard.internal;
+
+import java.util.Dictionary;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+public class WhiteboardServiceFactory implements ManagedServiceFactory {
+
+    public WhiteboardServiceFactory(BundleContext bundleContext) {
+        _bundleContext = bundleContext;
+    }
+
+    @Override
+    public String getName() {
+        return "org.apache.aries.jax.rs.whiteboard";
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void updated(String pid, Dictionary<String, ?> configuration)
+        throws ConfigurationException {
+
+        Whiteboard whiteboard = _whiteboards.remove(pid);
+
+        if (whiteboard != null) {
+            whiteboard.close();
+        }
+
+        _whiteboards.put(
+            pid, new Whiteboard(_bundleContext, (Map<String, Object>)Maps.from(configuration)));
+    }
+
+    @Override
+    public void deleted(String pid) {
+        Whiteboard whiteboard = _whiteboards.remove(pid);
+
+        if (whiteboard != null) {
+            whiteboard.close();
+        }
+    }
+
+    private final BundleContext _bundleContext;
+    private final Map<String, Whiteboard> _whiteboards = new ConcurrentHashMap<>();
+
+}
\ No newline at end of file


Mime
View raw message