This is an automated email from the ASF dual-hosted git repository.

amichai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-rsa.git

commit b6eeaf559705b5f65d3f1fbdfb53ddd3a3c3d3da
Author: Amichai Rothman <[email protected]>
AuthorDate: Sun Mar 15 16:28:41 2026 +0200

    Refactor ServiceExportsRepository
---
 .../exporter/ServiceExportsRepository.java         | 112 ++++++++-------------
 1 file changed, 42 insertions(+), 70 deletions(-)

diff --git 
a/topology-manager/src/main/java/org/apache/aries/rsa/topologymanager/exporter/ServiceExportsRepository.java
 
b/topology-manager/src/main/java/org/apache/aries/rsa/topologymanager/exporter/ServiceExportsRepository.java
index 5373cb78..179df20c 100644
--- 
a/topology-manager/src/main/java/org/apache/aries/rsa/topologymanager/exporter/ServiceExportsRepository.java
+++ 
b/topology-manager/src/main/java/org/apache/aries/rsa/topologymanager/exporter/ServiceExportsRepository.java
@@ -20,6 +20,7 @@ package org.apache.aries.rsa.topologymanager.exporter;
 
 import java.io.Closeable;
 import java.util.*;
+import java.util.stream.Collectors;
 
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.remoteserviceadmin.EndpointDescription;
@@ -39,104 +40,75 @@ public class ServiceExportsRepository implements Closeable 
{
 
     private final RemoteServiceAdmin rsa;
     private final EndpointListenerNotifier notifier;
-    private final Map<ServiceReference<?>, 
Collection<ExportRegistrationHolder>> exportsMap = new LinkedHashMap<>();
-
-    /**
-     * The holder allows us to work around that registration.getReference() is 
null when the registration is closed.
-     */
-    private class ExportRegistrationHolder {
-        private final ExportRegistration registration;
-        private final ExportReference reference;
-        private EndpointDescription endpoint;
-
-        ExportRegistrationHolder(ExportRegistration registration, 
EndpointDescription endpoint) {
-            this.registration = registration;
-            this.reference = registration.getExportReference();
-            this.endpoint = endpoint;
-            notifier.sendEvent(new EndpointEvent(EndpointEvent.ADDED, 
endpoint));
-        }
-
-        ExportRegistration getRegistration() {
-            return registration;
-        }
-
-        void close() {
-            if (reference != null) {
-                notifier.sendEvent(new EndpointEvent(EndpointEvent.REMOVED, 
endpoint));
-                registration.close();
-            }
-        }
-
-        public void update(ServiceReference<?> sref) {
-            if (reference != null) {
-                endpoint = registration.update(getServiceProps(sref));
-                notifier.sendEvent(new EndpointEvent(EndpointEvent.MODIFIED, 
endpoint));
-            }
-        }
-
-        private Map<String, ?> getServiceProps(ServiceReference<?> sref) {
-            HashMap<String, Object> props = new HashMap<>();
-            for (String key : sref.getPropertyKeys()) {
-                props.put(key, sref.getProperty(key));
-            }
-            return props;
-        }
-    }
+    // holds the set of exports for each service, and also caches the endpoint 
associated with each export,
+    // so we'll be able to access it even after it becomes unreachable via the 
export when it is closed
+    private final Map<ServiceReference<?>, Map<ExportRegistration, 
EndpointDescription>> exports = new LinkedHashMap<>();
 
     public ServiceExportsRepository(RemoteServiceAdmin rsa, 
EndpointListenerNotifier notifier) {
         this.rsa = rsa;
         this.notifier = notifier;
     }
 
+    private static Map<String, Object> getServiceProps(ServiceReference<?> 
sref) {
+        HashMap<String, Object> props = new HashMap<>();
+        for (String key : sref.getPropertyKeys()) {
+            props.put(key, sref.getProperty(key));
+        }
+        return props;
+    }
+
     @Override
     public synchronized void close() {
         LOG.debug("Closing registry for RemoteServiceAdmin {}", 
rsa.getClass().getName());
-        for (ServiceReference<?> sref : new ArrayList<>(exportsMap.keySet())) 
{ // iterate over copy to avoid CME
-            removeService(sref);
-        }
+        new ArrayList<>(exports.keySet()).forEach(this::removeService); // 
iterate over copy to avoid CME
     }
 
     public synchronized void addService(ServiceReference<?> sref, 
Collection<ExportRegistration> registrations) {
-        Collection<ExportRegistrationHolder> exports = new 
ArrayList<>(registrations.size());
+        Map<ExportRegistration, EndpointDescription> regs = new 
LinkedHashMap<>();
         for (ExportRegistration reg : registrations) {
-            ExportReference reference = reg.getExportReference();
-            if (reference != null) {
-                exports.add(new ExportRegistrationHolder(reg, 
reference.getExportedEndpoint()));
+            ExportReference ref = reg.getExportReference();
+            EndpointDescription endpoint = ref == null ? null : 
ref.getExportedEndpoint();
+            if (endpoint != null) {
+                regs.put(reg, endpoint);
+                notifier.sendEvent(new EndpointEvent(EndpointEvent.ADDED, 
endpoint));
             }
         }
-        if (!exports.isEmpty()) {
-            exportsMap.put(sref, exports);
+        if (!regs.isEmpty()) {
+            exports.put(sref, regs);
         }
     }
 
     public synchronized void modifyService(ServiceReference<?> sref) {
-        Collection<ExportRegistrationHolder> exports = exportsMap.get(sref);
-        if (exports != null) {
-            for (ExportRegistrationHolder reg : exports) {
-                reg.update(sref);
+        Map<ExportRegistration, EndpointDescription> regs = exports.get(sref);
+        if (regs != null) {
+            Map<String, ?> props = getServiceProps(sref);
+            for (Map.Entry<ExportRegistration, EndpointDescription> entry: 
regs.entrySet()) {
+                EndpointDescription updated = entry.getKey().update(props);
+                if (updated != null) {
+                    entry.setValue(updated);
+                    notifier.sendEvent(new 
EndpointEvent(EndpointEvent.MODIFIED, updated));
+                }
             }
         }
     }
 
     public synchronized void removeService(ServiceReference<?> sref) {
-        Collection<ExportRegistrationHolder> exports = exportsMap.remove(sref);
-        if (exports != null) {
-            for (ExportRegistrationHolder reg : exports) {
+        Map<ExportRegistration, EndpointDescription> regs = 
exports.remove(sref);
+        if (regs != null) {
+            regs.forEach((reg, endpoint) -> {
+                notifier.sendEvent(new EndpointEvent(EndpointEvent.REMOVED, 
endpoint));
                 reg.close();
-            }
+            });
         }
     }
 
     public synchronized List<EndpointDescription> getAllEndpoints() {
-        List<EndpointDescription> endpoints = new ArrayList<>();
-        for (Collection<ExportRegistrationHolder> exports : 
exportsMap.values()) {
-            for (ExportRegistrationHolder reg : exports) {
-                ExportReference reference = 
reg.getRegistration().getExportReference();
-                if (reference != null) {
-                    endpoints.add(reference.getExportedEndpoint());
-                }
-            }
-        }
-        return endpoints;
+        return exports.values().stream()
+            .flatMap(regs -> regs.keySet().stream())
+            .map(ExportRegistration::getExportReference)
+            .filter(Objects::nonNull)
+            .map(ExportReference::getExportedEndpoint)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toList());
     }
 }

Reply via email to