X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fruntime%2FCmsContextImpl.java;h=bd54b20594b5e7200d0a3e04f975e8cfc13ab354;hb=55870eba50d8b28e72a3102fd18a17a6f23f7bad;hp=ea9a401a4d3fc49ee2f617558432dbc11f170024;hpb=60aa2e64061a09e938d9f6cba35ee3fd66a19828;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java index ea9a401a4..bd54b2059 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java @@ -3,23 +3,18 @@ package org.argeo.cms.internal.runtime; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.HashMap; -import java.util.IdentityHashMap; 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; @@ -30,19 +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 final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); -// private EgoRepository egoRepository; private static CompletableFuture instance = new CompletableFuture(); private CmsState cmsState; private CmsDeployment cmsDeployment; private UserAdmin userAdmin; private UuidFactory uuidFactory; -// private ProvidedRepository contentRepository; + private CmsEventBus cmsEventBus; // i18n private Locale defaultLocale; @@ -54,46 +48,21 @@ public class CmsContextImpl implements CmsContext { private Map cmsSessionsByUuid = new HashMap<>(); private Map cmsSessionsByLocalId = new HashMap<>(); - // CMS events - private Map>> topics = new TreeMap<>(); -// private IdentityHashMap> subscriptions = new IdentityHashMap<>(); - -// public CmsContextImpl() { -// initTrackers(); -// } - public void start() { List codes = CmsStateImpl.getDeployProperties(cmsState, CmsDeployProperty.LOCALE); locales = getLocaleList(codes); if (locales.size() == 0) throw new IllegalStateException("At least one locale must be set"); defaultLocale = locales.get(0); -// Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE); -// defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) -// : new Locale(ENGLISH.getLanguage()); - // node repository -// new ServiceTracker(bc, Repository.class, null) { -// @Override -// public Repository addingService(ServiceReference reference) { -// Object cn = reference.getProperty(NodeConstants.CN); -// if (cn != null && cn.equals(NodeConstants.EGO_REPOSITORY)) { -//// egoRepository = (EgoRepository) bc.getService(reference); -// if (log.isTraceEnabled()) -// log.trace("Home repository is available"); -// } -// return super.addingService(reference); -// } -// -// @Override -// public void removedService(ServiceReference reference, Repository service) { -// super.removedService(reference, service); -//// egoRepository = null; -// } -// -// }.open(); - - checkReadiness(); + new Thread(() -> { + while (!checkReadiness()) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + } + }, "Check readiness").start(); setInstance(this); } @@ -105,10 +74,13 @@ public class CmsContextImpl implements CmsContext { * Checks whether the deployment is available according to expectations, and * mark it as available. */ - private void checkReadiness() { + private boolean checkReadiness() { if (isAvailable()) - return; - if (cmsDeployment != null && userAdmin != null) { + return true; + if (cmsDeployment == null) + return false; + + if (((CmsDeploymentImpl) cmsDeployment).allExpectedServicesAvailable() && userAdmin != null) { String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA); String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA); availableSince = System.currentTimeMillis(); @@ -125,8 +97,11 @@ public class CmsContextImpl implements CmsContext { if (log.isTraceEnabled()) log.trace("Kernel initialization took " + initDuration + "ms"); tributeToFreeSoftware(initDuration); + + return true; } else { - throw new IllegalStateException("Deployment is not available"); + return false; + // throw new IllegalStateException("Deployment is not available"); } } @@ -199,69 +174,70 @@ 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 getLocales() { return locales; } @Override - public synchronized Long getAvailableSince() { + public Long getAvailableSince() { return availableSince; } - public synchronized boolean isAvailable() { + public boolean isAvailable() { return availableSince != null; } - @Override public CmsState getCmsState() { return cmsState; } + @Override + public CmsEventBus getCmsEventBus() { + return cmsEventBus; + } + + public void setCmsEventBus(CmsEventBus cmsEventBus) { + this.cmsEventBus = cmsEventBus; + } + /* * STATIC */ - public synchronized static CmsContextImpl getCmsContext() { + public static CmsContextImpl getCmsContext() { return getInstance(); } -// /** Required by USER login module. */ -// public synchronized static UserAdmin getUserAdmin() { -// return getInstance().userAdmin; -// } - /** Required by SPNEGO login module. */ - @Deprecated - public synchronized static GSSCredential getAcceptorCredentials() { - // FIXME find a cleaner way - return ((CmsUserAdmin) getInstance().userAdmin).getAcceptorCredentials(); + public GSSCredential getAcceptorCredentials() { + // TODO find a cleaner way + return ((CmsUserAdmin) userAdmin).getAcceptorCredentials(); } - private synchronized static void setInstance(CmsContextImpl cmsContextImpl) { + private static void setInstance(CmsContextImpl cmsContextImpl) { 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(); } } - private synchronized static CmsContextImpl getInstance() { + private static CmsContextImpl getInstance() { try { return instance.get(); } catch (InterruptedException | ExecutionException e) { @@ -278,14 +254,14 @@ public class CmsContextImpl implements CmsContext { */ @Override - public synchronized CmsSession getCmsSession(Subject subject) { + public CmsSession getCmsSession(Subject subject) { if (subject.getPrivateCredentials(CmsSessionId.class).isEmpty()) return null; CmsSessionId cmsSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next(); return getCmsSessionByUuid(cmsSessionId.getUuid()); } - public synchronized void registerCmsSession(CmsSessionImpl cmsSession) { + public void registerCmsSession(CmsSessionImpl cmsSession) { if (cmsSessionsByUuid.containsKey(cmsSession.getUuid()) || cmsSessionsByLocalId.containsKey(cmsSession.getLocalId())) throw new IllegalStateException("CMS session " + cmsSession + " is already registered."); @@ -293,7 +269,7 @@ public class CmsContextImpl implements CmsContext { cmsSessionsByLocalId.put(cmsSession.getLocalId(), cmsSession); } - public synchronized void unregisterCmsSession(CmsSessionImpl cmsSession) { + public void unregisterCmsSession(CmsSessionImpl cmsSession) { if (!cmsSessionsByUuid.containsKey(cmsSession.getUuid()) || !cmsSessionsByLocalId.containsKey(cmsSession.getLocalId())) throw new IllegalStateException("CMS session " + cmsSession + " is not registered."); @@ -306,7 +282,7 @@ public class CmsContextImpl implements CmsContext { * The {@link CmsSession} related to this UUID, or null if not * registered. */ - public synchronized CmsSessionImpl getCmsSessionByUuid(UUID uuid) { + public CmsSessionImpl getCmsSessionByUuid(UUID uuid) { return cmsSessionsByUuid.get(uuid); } @@ -314,90 +290,8 @@ public class CmsContextImpl implements CmsContext { * The {@link CmsSession} related to this local id, or null if not * registered. */ - public synchronized CmsSessionImpl getCmsSessionByLocalId(String localId) { + public CmsSessionImpl getCmsSessionByLocalId(String localId) { return cmsSessionsByLocalId.get(localId); } - /* - * CMS Events - */ - public void sendEvent(String topic, Map event) { - SubmissionPublisher> 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> publisher = topics.get(topic); - CmsEventFlowSubscriber flowSubscriber = new CmsEventFlowSubscriber(topic, subscriber); - publisher.subscribe(flowSubscriber); - } - - public void removeEventSubscriber(String topic, CmsEventSubscriber subscriber) { - SubmissionPublisher> publisher = topics.get(topic); - if (publisher == null) { - log.error("There should be an event topic " + topic); - return; - } - for (Flow.Subscriber> 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> { - 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 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"); - } - - } - }