Refactor Argeo init
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / runtime / CmsContextImpl.java
index af45b74e31c7d640cb53c9136abc1b6fc7608da2..25f8dad6a784f1c496b6ff3a2b2efaa941e2512d 100644 (file)
@@ -6,19 +6,15 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.TreeMap;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Flow;
-import java.util.concurrent.Flow.Subscription;
-import java.util.concurrent.SubmissionPublisher;
 
 import javax.security.auth.Subject;
 
 import org.argeo.api.cms.CmsContext;
 import org.argeo.api.cms.CmsDeployment;
-import org.argeo.api.cms.CmsEventSubscriber;
+import org.argeo.api.cms.CmsEventBus;
 import org.argeo.api.cms.CmsLog;
 import org.argeo.api.cms.CmsSession;
 import org.argeo.api.cms.CmsSessionId;
@@ -29,18 +25,18 @@ import org.argeo.cms.internal.auth.CmsSessionImpl;
 import org.ietf.jgss.GSSCredential;
 import org.osgi.service.useradmin.UserAdmin;
 
+/** Reference implementation of {@link CmsContext}. */
 public class CmsContextImpl implements CmsContext {
 
        private final CmsLog log = CmsLog.getLog(getClass());
 
        private static CompletableFuture<CmsContextImpl> instance = new CompletableFuture<CmsContextImpl>();
-//     private static CmsContextImpl instance = null;
 
        private CmsState cmsState;
        private CmsDeployment cmsDeployment;
        private UserAdmin userAdmin;
        private UuidFactory uuidFactory;
-//     private ProvidedRepository contentRepository;
+       private CmsEventBus cmsEventBus;
 
        // i18n
        private Locale defaultLocale;
@@ -48,14 +44,13 @@ public class CmsContextImpl implements CmsContext {
 
        private Long availableSince;
 
+       // time in ms to wait for CMS to be ready
+       private final long readynessTimeout = 30 * 1000;
+
        // CMS sessions
        private Map<UUID, CmsSessionImpl> cmsSessionsByUuid = new HashMap<>();
        private Map<String, CmsSessionImpl> cmsSessionsByLocalId = new HashMap<>();
 
-       // CMS events
-       private Map<String, SubmissionPublisher<Map<String, Object>>> topics = new TreeMap<>();
-//     private IdentityHashMap<CmsEventSubscriber, List<CmsEventFlowSubscriber>> subscriptions = new IdentityHashMap<>();
-
        public void start() {
                List<String> codes = CmsStateImpl.getDeployProperties(cmsState, CmsDeployProperty.LOCALE);
                locales = getLocaleList(codes);
@@ -64,16 +59,20 @@ public class CmsContextImpl implements CmsContext {
                defaultLocale = locales.get(0);
 
                new Thread(() -> {
-                       while (!checkReadiness()) {
+                       long begin = System.currentTimeMillis();
+                       long duration = 0;
+                       readyness: while (!checkReadiness()) {
+                               duration = System.currentTimeMillis() - begin;
+                               if (duration > readynessTimeout) {
+                                       log.error("## CMS not ready after " + duration + " ms. Giving up checking.");
+                                       break readyness;
+                               }
                                try {
-                                       Thread.sleep(500);
+                                       Thread.sleep(100);
                                } catch (InterruptedException e) {
                                }
                        }
                }, "Check readiness").start();
-
-               // checkReadiness();
-
                setInstance(this);
        }
 
@@ -97,7 +96,8 @@ public class CmsContextImpl implements CmsContext {
                        availableSince = System.currentTimeMillis();
                        long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
                        String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s";
-                       log.info("## ARGEO CMS AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##");
+                       log.info("## ARGEO CMS " + cmsState.getUuid() + " AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "")
+                                       + " ##");
                        if (log.isDebugEnabled()) {
                                log.debug("## state: " + state);
                                if (data != null)
@@ -185,19 +185,16 @@ public class CmsContextImpl implements CmsContext {
                this.uuidFactory = uuidFactory;
        }
 
-//     public ProvidedRepository getContentRepository() {
-//             return contentRepository;
-//     }
-//
-//     public void setContentRepository(ProvidedRepository contentRepository) {
-//             this.contentRepository = contentRepository;
-//     }
-
        @Override
        public Locale getDefaultLocale() {
                return defaultLocale;
        }
 
+       @Override
+       public UUID timeUUID() {
+               return uuidFactory.timeUUID();
+       }
+
        @Override
        public List<Locale> getLocales() {
                return locales;
@@ -212,11 +209,19 @@ public class CmsContextImpl implements CmsContext {
                return availableSince != null;
        }
 
-       @Override
        public CmsState getCmsState() {
                return cmsState;
        }
 
+       @Override
+       public CmsEventBus getCmsEventBus() {
+               return cmsEventBus;
+       }
+
+       public void setCmsEventBus(CmsEventBus cmsEventBus) {
+               this.cmsEventBus = cmsEventBus;
+       }
+
        /*
         * STATIC
         */
@@ -226,40 +231,24 @@ public class CmsContextImpl implements CmsContext {
        }
 
        /** Required by SPNEGO login module. */
-       public static GSSCredential getAcceptorCredentials() {
+       public GSSCredential getAcceptorCredentials() {
                // TODO find a cleaner way
-               return ((CmsUserAdmin) getInstance().userAdmin).getAcceptorCredentials();
+               return ((CmsUserAdmin) userAdmin).getAcceptorCredentials();
        }
 
        private static void setInstance(CmsContextImpl cmsContextImpl) {
-//             if (cmsContextImpl != null) {
-//                     if (instance != null)
-//                             throw new IllegalStateException("CMS Context is already set");
-//                     instance = cmsContextImpl;
-//             } else {
-//                     instance = null;
-//             }
-//             CmsContextImpl.class.notifyAll();
-               
                if (cmsContextImpl != null) {
                        if (instance.isDone())
                                throw new IllegalStateException("CMS Context is already set");
                        instance.complete(cmsContextImpl);
                } else {
+                       if (!instance.isDone())
+                               instance.cancel(true);
                        instance = new CompletableFuture<CmsContextImpl>();
                }
        }
 
        private static CmsContextImpl getInstance() {
-//             while (instance == null) {
-//                     try {
-//                             CmsContextImpl.class.wait();
-//                     } catch (InterruptedException e) {
-//                             throw new IllegalStateException("Cannot wait for CMS context instance", e);
-//                     }
-//             }
-//             return instance;
-
                try {
                        return instance.get();
                } catch (InterruptedException | ExecutionException e) {
@@ -316,86 +305,4 @@ public class CmsContextImpl implements CmsContext {
                return cmsSessionsByLocalId.get(localId);
        }
 
-       /*
-        * CMS Events
-        */
-       public void sendEvent(String topic, Map<String, Object> event) {
-               SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
-               if (publisher == null)
-                       return; // no one is interested
-               publisher.submit(event);
-       }
-
-       public void addEventSubscriber(String topic, CmsEventSubscriber subscriber) {
-               synchronized (topics) {
-                       if (!topics.containsKey(topic))
-                               topics.put(topic, new SubmissionPublisher<>());
-               }
-               SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
-               CmsEventFlowSubscriber flowSubscriber = new CmsEventFlowSubscriber(topic, subscriber);
-               publisher.subscribe(flowSubscriber);
-       }
-
-       public void removeEventSubscriber(String topic, CmsEventSubscriber subscriber) {
-               SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
-               if (publisher == null) {
-                       log.error("There should be an event topic " + topic);
-                       return;
-               }
-               for (Flow.Subscriber<? super Map<String, Object>> flowSubscriber : publisher.getSubscribers()) {
-                       if (flowSubscriber instanceof CmsEventFlowSubscriber)
-                               ((CmsEventFlowSubscriber) flowSubscriber).unsubscribe();
-               }
-               synchronized (topics) {
-                       if (!publisher.hasSubscribers()) {
-                               publisher.close();
-                               topics.remove(topic);
-                       }
-               }
-       }
-
-       static class CmsEventFlowSubscriber implements Flow.Subscriber<Map<String, Object>> {
-               private String topic;
-               private CmsEventSubscriber eventSubscriber;
-
-               private Subscription subscription;
-
-               public CmsEventFlowSubscriber(String topic, CmsEventSubscriber eventSubscriber) {
-                       this.topic = topic;
-                       this.eventSubscriber = eventSubscriber;
-               }
-
-               @Override
-               public void onSubscribe(Subscription subscription) {
-                       this.subscription = subscription;
-                       subscription.request(Long.MAX_VALUE);
-               }
-
-               @Override
-               public void onNext(Map<String, Object> item) {
-                       eventSubscriber.onEvent(topic, item);
-
-               }
-
-               @Override
-               public void onError(Throwable throwable) {
-                       // TODO Auto-generated method stub
-
-               }
-
-               @Override
-               public void onComplete() {
-                       // TODO Auto-generated method stub
-
-               }
-
-               void unsubscribe() {
-                       if (subscription != null)
-                               subscription.cancel();
-                       else
-                               throw new IllegalStateException("No subscription to cancel");
-               }
-
-       }
-
 }