Repository: aries-jax-rs-whiteboard
Updated Branches:
  refs/heads/master f37e0dd82 -> 31bf73834


Factor clashing detection logic out


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

Branch: refs/heads/master
Commit: 31bf73834766999fe0315aa62d340b64ea35b7e7
Parents: ffc1175
Author: Carlos Sierra <[email protected]>
Authored: Fri Aug 18 14:35:14 2017 +0200
Committer: Carlos Sierra <[email protected]>
Committed: Fri Aug 18 15:59:21 2017 +0200

----------------------------------------------------------------------
 .../internal/AriesJaxRSServiceRuntime.java      | 153 +++----------------
 .../aries/jax/rs/whiteboard/internal/Utils.java | 114 +++++++++++++-
 .../jax/rs/whiteboard/internal/Whiteboard.java  |  69 ++++++---
 3 files changed, 183 insertions(+), 153 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/31bf7383/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 11e9772..67166b0 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
@@ -17,8 +17,6 @@
 
 package org.apache.aries.jax.rs.whiteboard.internal;
 
-import org.apache.aries.osgi.functional.Event;
-import org.apache.aries.osgi.functional.OSGi;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.jaxrs.runtime.JaxRSServiceRuntime;
@@ -31,33 +29,27 @@ import 
org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants;
 
 import javax.ws.rs.core.Application;
 import java.util.Comparator;
-import java.util.Objects;
+import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Stream;
 
-import static 
org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_APPLICATION_BASE;
 import static 
org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_NAME;
 
 public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime {
 
     private static final long serialVersionUID = 1L;
 
-    private ConcurrentHashMap<String, 
TreeSet<Event<MutableTuple<Application>>>>
+    private ConcurrentHashMap<String, ServiceReference<Application>>
         _applications = new ConcurrentHashMap<>();
 
     private TreeSet<ServiceReference<Application>>
         _ungettableApplications;
 
-    private Comparator<Event<MutableTuple<Application>>>
-        _applicationComparator;
+    private Set<ServiceReference<Application>> _shadowedApplications =
+        new TreeSet<>();
 
     public AriesJaxRSServiceRuntime(BundleContext bundleContext) {
-        _applicationComparator = Comparator.comparing(
-            Event::getContent);
-
-        _applicationComparator = _applicationComparator.reversed();
-
         _ungettableApplications = new TreeSet<>(Comparator.reverseOrder());
     }
 
@@ -73,69 +65,26 @@ public class AriesJaxRSServiceRuntime implements 
JaxRSServiceRuntime {
         return _ungettableApplications.remove(serviceReference);
     }
 
-    public OSGi<MutableTuple<Application>> processApplications(
-        OSGi<MutableTuple<Application>> source) {
-
-        return
-            source.route(
-                router -> {
-                router.onIncoming(event -> {
-                    MutableTuple<Application>
-                        tuple = event.getContent();
-
-                    ServiceReference<Application> serviceReference =
-                        tuple.getServiceReference();
-
-                    String path = 
serviceReference.getProperty(JAX_RS_APPLICATION_BASE).
-                        toString();
-
-                    TreeSet<Event<MutableTuple<Application>>> 
applicationReferences =
-                        _applications.computeIfAbsent(
-                            path, __ -> new TreeSet<>(_applicationComparator));
-
-                    Event<MutableTuple<Application>> first =
-                        applicationReferences.size() > 0 ? 
applicationReferences.first() : null;
-
-                    if (first == null || _applicationComparator.compare(event, 
first) < 0) {
-                        if (first != null) {
-                            router.signalLeave(first);
-                        }
-
-                        router.signalAdd(event);
-                    }
-
-                    applicationReferences.add(event);
-                });
-                router.onLeaving(event -> {
-                    MutableTuple<Application> tuple = event.getContent();
+    public ServiceReference<Application> setApplicationForPath(
+        String path, ServiceReference<Application> serviceReference) {
 
-                    ServiceReference<Application> serviceReference =
-                        tuple.getServiceReference();
-
-                    String path = 
serviceReference.getProperty(JAX_RS_APPLICATION_BASE).
-                        toString();
-
-                    TreeSet<Event<MutableTuple<Application>>>
-                        applicationReferences = _applications.get(path);
+        return _applications.put(path, serviceReference);
+    }
 
-                    Event<MutableTuple<Application>> first =
-                        applicationReferences.first();
+    public ServiceReference<Application> unsetApplicationForPath(String path) {
+        return _applications.remove(path);
+    }
 
-                    if (tuple.equals(first.getContent())) {
-                        router.signalLeave(first);
+    public boolean addShadowedApplication(
+        ServiceReference<Application> serviceReference) {
 
-                        Event<MutableTuple<Application>> second =
-                            applicationReferences.higher(first);
+        return _shadowedApplications.add(serviceReference);
+    }
 
-                        if (second != null) {
-                            router.signalAdd(second);
-                        }
-                    }
+    public boolean removeShadowedApplication(
+        ServiceReference<Application> serviceReference) {
 
-                    applicationReferences.removeIf(
-                        t -> t.getContent().equals(tuple));
-                });
-            });
+        return _shadowedApplications.remove(serviceReference);
     }
 
     @Override
@@ -164,15 +113,7 @@ public class AriesJaxRSServiceRuntime implements 
JaxRSServiceRuntime {
 
     private Stream<ApplicationDTO> applicationDTOStream() {
         return _applications.values().stream().
-            flatMap(
-                tree -> tree.size() > 0 ? Stream.of(tree.first()) : 
Stream.empty()
-            ).filter(
-                Objects::nonNull
-            ).map(
-                Event::getContent
-            ).map(
-                MutableTuple::getServiceReference
-            ).map(
+            map(
                 AriesJaxRSServiceRuntime::buildApplicationDTO
             );
     }
@@ -187,16 +128,8 @@ public class AriesJaxRSServiceRuntime implements 
JaxRSServiceRuntime {
     }
 
     private Stream<FailedApplicationDTO> shadowedApplications() {
-        return _applications.values().stream().flatMap(
-            tree -> tree.size() > 0 ? tree.tailSet(tree.first(), 
false).stream() : Stream.empty()
-        ).filter(
-            Objects::nonNull
-        ).map(
-            Event::getContent
-        ).map(
-            MutableTuple::getServiceReference
-        ).map(
-            sr -> buildFailedApplicationDTO(
+        return _shadowedApplications.stream().
+            map(sr -> buildFailedApplicationDTO(
                 DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE,
                 sr)
         );
@@ -248,48 +181,4 @@ public class AriesJaxRSServiceRuntime implements 
JaxRSServiceRuntime {
             serviceReference.getProperty("service.id").toString();
     }
 
-    public static class MutableTuple<T> implements Comparable<MutableTuple<T>> 
{
-
-        private final ServiceReference<T> _serviceReference;
-        private T _service;
-
-        public MutableTuple(ServiceReference<T> a, T service) {
-            _serviceReference = a;
-            _service = service;
-        }
-
-        @Override
-        public int compareTo(MutableTuple<T> o) {
-            return _serviceReference.compareTo(o._serviceReference);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            MutableTuple<?> that = (MutableTuple<?>) o;
-
-            return _serviceReference.equals(that._serviceReference);
-        }
-
-        @Override
-        public int hashCode() {
-            return _serviceReference.hashCode();
-        }
-
-        public ServiceReference<T> getServiceReference() {
-            return _serviceReference;
-        }
-
-        public T getSecond() {
-            return _service;
-        }
-
-        public void setService(T service) {
-            _service = service;
-        }
-
-    }
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/31bf7383/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 9846ebb..69310a4 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
@@ -17,7 +17,6 @@
 
 package org.apache.aries.jax.rs.whiteboard.internal;
 
-import 
org.apache.aries.jax.rs.whiteboard.internal.AriesJaxRSServiceRuntime.MutableTuple;
 import org.apache.aries.osgi.functional.Event;
 import org.apache.aries.osgi.functional.OSGi;
 import org.apache.cxf.Bus;
@@ -31,9 +30,12 @@ import javax.ws.rs.core.Application;
 import javax.ws.rs.ext.Provider;
 import java.util.Comparator;
 import java.util.Map;
+import java.util.NavigableSet;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 import static org.apache.aries.osgi.functional.OSGi.bundleContext;
 import static org.apache.aries.osgi.functional.OSGi.just;
@@ -234,6 +236,73 @@ public class Utils {
 
     }
 
+    public static <K, T extends Comparable<? super T>> OSGi<T> highestPer(
+        Function<T, K> keySupplier, OSGi<T> program,
+        Consumer<T> onAddingShadowed, Consumer<T> onRemovedShadowed) {
+
+        ConcurrentHashMap<K, TreeSet<Event<T>>> map = new 
ConcurrentHashMap<>();
+
+        return program.route(
+            router -> {
+                router.onIncoming(e -> {
+                    K key = keySupplier.apply(e.getContent());
+
+                    Comparator<Event<T>> comparator = Comparator.comparing(
+                        Event::getContent);
+
+                    NavigableSet<Event<T>> set = map.computeIfAbsent(
+                        key, __ -> new TreeSet<>(comparator));
+
+                    Event<T> last = set.size() > 0 ? set.last() : null;
+
+                    boolean higher =
+                        (last == null) || (comparator.compare(e, last) > 0);
+
+                    if (higher) {
+                        if (last != null) {
+                            router.signalLeave(last);
+
+                            onAddingShadowed.accept(last.getContent());
+                        }
+
+                        router.signalAdd(e);
+                    }
+                    else {
+                        onAddingShadowed.accept(e.getContent());
+                    }
+
+                    set.add(e);
+                });
+                router.onLeaving(e -> {
+                    T content = e.getContent();
+
+                    K key = keySupplier.apply(content);
+
+                    TreeSet<Event<T>> set = map.get(key);
+
+                    Event<T> last = set.last();
+
+                    if (content.equals(last.getContent())) {
+                        router.signalLeave(e);
+
+                        Event<T> penultimate = set.lower(last);
+
+                        if (penultimate != null) {
+                            router.signalAdd(penultimate);
+
+                            onRemovedShadowed.accept(penultimate.getContent());
+                        }
+                    }
+                    else {
+                        onRemovedShadowed.accept(content);
+                    }
+
+                    set.removeIf(t -> t.getContent().equals(content));
+                });
+            }
+        );
+    }
+
     public static class ComparableResourceProvider
         implements ResourceProvider, Comparable<ComparableResourceProvider> {
 
@@ -284,4 +353,47 @@ public class Utils {
 
     }
 
+    public static class MutableTuple<T> implements Comparable<MutableTuple<T>> 
{
+
+        private final ServiceReference<T> _serviceReference;
+        private T _service;
+
+        public MutableTuple(ServiceReference<T> a, T service) {
+            _serviceReference = a;
+            _service = service;
+        }
+
+        @Override
+        public int compareTo(MutableTuple<T> o) {
+            return _serviceReference.compareTo(o._serviceReference);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            MutableTuple<?> that = (MutableTuple<?>) o;
+
+            return _serviceReference.equals(that._serviceReference);
+        }
+
+        @Override
+        public int hashCode() {
+            return _serviceReference.hashCode();
+        }
+
+        public ServiceReference<T> getServiceReference() {
+            return _serviceReference;
+        }
+
+        public T getSecond() {
+            return _service;
+        }
+
+        public void setService(T service) {
+            _service = service;
+        }
+
+    }
 }

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/31bf7383/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 d4a4178..99980bb 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
@@ -17,7 +17,7 @@
 
 package org.apache.aries.jax.rs.whiteboard.internal;
 
-import 
org.apache.aries.jax.rs.whiteboard.internal.AriesJaxRSServiceRuntime.MutableTuple;
+import org.apache.aries.jax.rs.whiteboard.internal.Utils.MutableTuple;
 import org.apache.aries.osgi.functional.OSGi;
 import org.apache.cxf.Bus;
 import org.apache.cxf.bus.extension.ExtensionManagerBus;
@@ -41,9 +41,11 @@ import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
 
 import static java.lang.String.format;
 import static 
org.apache.aries.jax.rs.whiteboard.internal.Utils.deployRegistrator;
+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.safeRegisterEndpoint;
 import static 
org.apache.aries.jax.rs.whiteboard.internal.Utils.safeRegisterExtension;
@@ -72,6 +74,9 @@ import static 
org.osgi.service.jaxrs.whiteboard.JaxRSWhiteboardConstants.JAX_RS_
  * @author Carlos Sierra Andrés
  */
 public class Whiteboard {
+
+    public static final Function<MutableTuple<Application>, String> 
APPLICATION_BASE = ((Function<MutableTuple<Application>, 
ServiceReference<Application>>) 
Utils.MutableTuple::getServiceReference).andThen(Whiteboard::getApplicationBase);
+
     public static OSGi<Void> createWhiteboard(Dictionary<String, ?> 
configuration) {
 
 
@@ -231,40 +236,56 @@ public class Whiteboard {
         AriesJaxRSServiceRuntime runtime,
         Map<String, ?> configuration) {
 
-        OSGi<MutableTuple<Application>> applicationsForWhiteboard =
-            getApplicationsForWhiteboard(jaxRsRuntimeServiceReference).
-                flatMap(
-                    sr -> onlyGettables(
-                        sr, runtime::addNotGettable, 
runtime::removeNotGettable)
-                );
+        OSGi<MutableTuple<Application>> gettableAplicationForWhiteboard =
+            getApplicationsForWhiteboard(jaxRsRuntimeServiceReference).flatMap(
+                sr -> onlyGettables(
+                    sr, runtime::addNotGettable, runtime::removeNotGettable)
+            );
+
+        OSGi<MutableTuple<Application>> highestRankedPerPath = highestPer(
+            APPLICATION_BASE,
+            gettableAplicationForWhiteboard,
+            t -> runtime.addShadowedApplication(t.getServiceReference()),
+            t -> runtime.removeShadowedApplication(t.getServiceReference())
+        );
 
         return
             bundleContext().flatMap(
-                bundleContext ->
-                    
runtime.processApplications(applicationsForWhiteboard).flatMap(
-                        ref -> deployApplication(
-                            configuration, bundleContext, ref)));
+                bundleContext -> highestRankedPerPath.flatMap(
+                    ref -> deployApplication(configuration, bundleContext, ref)
+                ).map(
+                    MutableTuple::getServiceReference).
+                foreach(
+                    sr -> runtime.setApplicationForPath(
+                            getApplicationBase(sr), sr),
+                    sr -> runtime.unsetApplicationForPath(
+                        getApplicationBase(sr))
+                )
+            );
     }
 
-    private static OSGi<Void> deployApplication(
+    private static OSGi<MutableTuple<Application>> deployApplication(
         Map<String, ?> configuration, BundleContext bundleContext,
         MutableTuple<Application> tuple) {
 
         ExtensionManagerBus bus = createBus(bundleContext, configuration);
 
-        ServiceReference<Application> serviceReference = 
tuple.getServiceReference();
+        ServiceReference<Application> serviceReference =
+            tuple.getServiceReference();
 
         Map<String, Object> properties =
             CXFJaxRsServiceRegistrator.getProperties(
                 serviceReference, JAX_RS_APPLICATION_BASE);
 
-        return all(
-            deployRegistrator(bus, tuple.getSecond(), properties),
-            registerCXFServletService(
-                bus, 
serviceReference.getProperty(JAX_RS_APPLICATION_BASE).toString(),
-                properties)
-        );
-
+        return
+            all(
+                deployRegistrator(bus, tuple.getSecond(), properties),
+                registerCXFServletService(
+                    bus, getApplicationBase(serviceReference),
+                    properties)).
+            then(
+                just(tuple)
+            );
     }
 
     private static OSGi<ServiceReference<Application>>
@@ -384,4 +405,12 @@ public class Whiteboard {
         }
     }
 
+    public static String getApplicationBase(
+        ServiceReference<Application> serviceReference) {
+
+        return 
serviceReference.getProperty(JAX_RS_APPLICATION_BASE).toString();
+    }
+
+
+
 }

Reply via email to