Start working around components
[lgpl/argeo-commons.git] / org.argeo.enterprise / src / org / argeo / osgi / util / OsgiRegister.java
diff --git a/org.argeo.enterprise/src/org/argeo/osgi/util/OsgiRegister.java b/org.argeo.enterprise/src/org/argeo/osgi/util/OsgiRegister.java
new file mode 100644 (file)
index 0000000..7132b7c
--- /dev/null
@@ -0,0 +1,60 @@
+package org.argeo.osgi.util;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ForkJoinPool;
+
+import org.argeo.util.register.Register;
+import org.argeo.util.register.Singleton;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class OsgiRegister implements Register {
+       private final BundleContext bundleContext;
+       private Executor executor;
+
+       private CompletableFuture<Void> shutdownStarting = new CompletableFuture<Void>();
+
+       public OsgiRegister(BundleContext bundleContext) {
+               this.bundleContext = bundleContext;
+               // TODO experiment with dedicated executors
+               this.executor = ForkJoinPool.commonPool();
+       }
+
+       @Override
+       public <T> Singleton<T> set(T obj, Class<T> clss, Map<String, Object> attributes, Class<?>... classes) {
+               CompletableFuture<ServiceRegistration<?>> srf = new CompletableFuture<ServiceRegistration<?>>();
+               CompletableFuture<T> postRegistration = CompletableFuture.supplyAsync(() -> {
+                       List<String> lst = new ArrayList<>();
+                       lst.add(clss.getName());
+                       for (Class<?> c : classes) {
+                               lst.add(c.getName());
+                       }
+                       ServiceRegistration<?> sr = bundleContext.registerService(lst.toArray(new String[lst.size()]), obj,
+                                       new Hashtable<String, Object>(attributes));
+                       srf.complete(sr);
+                       return obj;
+               }, executor);
+               Singleton<T> singleton = new Singleton<T>(clss, postRegistration);
+
+               shutdownStarting. //
+                               thenCompose(singleton::prepareUnregistration). //
+                               thenRunAsync(() -> {
+                                       try {
+                                               srf.get().unregister();
+                                       } catch (InterruptedException | ExecutionException e) {
+                                               e.printStackTrace();
+                                       }
+                               }, executor);
+               return singleton;
+       }
+
+       public void shutdown() {
+               shutdownStarting.complete(null);
+       }
+}