package org.argeo.cms.internal.runtime; import static java.util.Locale.ENGLISH; import java.lang.management.ManagementFactory; import java.util.List; import java.util.Locale; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsContext; import org.argeo.api.cms.CmsDeployment; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsState; import org.argeo.cms.LocaleUtils; import org.argeo.cms.internal.osgi.NodeUserAdmin; import org.ietf.jgss.GSSCredential; import org.osgi.service.useradmin.UserAdmin; 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; // i18n private Locale defaultLocale; private List locales = null; private Long availableSince; // public CmsContextImpl() { // initTrackers(); // } public void init() { Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE); defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) : new Locale(ENGLISH.getLanguage()); locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(CmsConstants.I18N_LOCALES)); // 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(); setInstance(this); } public void destroy() { setInstance(null); } /** * Checks whether the deployment is available according to expectations, and * mark it as available. */ private void checkReadiness() { if (isAvailable()) return; if (cmsDeployment != null && userAdmin != null) { String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA); String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA); availableSince = System.currentTimeMillis(); long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime(); String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s"; log.info("## ARGEO CMS AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##"); if (log.isDebugEnabled()) { log.debug("## state: " + state); if (data != null) log.debug("## data: " + data); } long begin = cmsState.getAvailableSince(); long initDuration = System.currentTimeMillis() - begin; if (log.isTraceEnabled()) log.trace("Kernel initialization took " + initDuration + "ms"); tributeToFreeSoftware(initDuration); } else { throw new IllegalStateException("Deployment is not available"); } } final private void tributeToFreeSoftware(long initDuration) { if (log.isTraceEnabled()) { long ms = initDuration / 100; log.trace("Spend " + ms + "ms" + " reflecting on the progress brought to mankind" + " by Free Software..."); long beginNano = System.nanoTime(); try { Thread.sleep(ms, 0); } catch (InterruptedException e) { // silent } long durationNano = System.nanoTime() - beginNano; final double M = 1000d * 1000d; double sleepAccuracy = ((double) durationNano) / (ms * M); log.trace("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %"); } } @Override public void createWorkgroup(String dn) { // if (egoRepository == null) // throw new CmsException("Ego repository is not available"); // // TODO add check that the group exists // egoRepository.createWorkgroup(dn); throw new UnsupportedOperationException(); } public void setCmsDeployment(CmsDeployment cmsDeployment) { this.cmsDeployment = cmsDeployment; } public void setCmsState(CmsState cmsState) { this.cmsState = cmsState; } public void setUserAdmin(UserAdmin userAdmin) { this.userAdmin = userAdmin; } @Override public Locale getDefaultLocale() { return defaultLocale; } @Override public List getLocales() { return locales; } @Override public synchronized Long getAvailableSince() { return availableSince; } public synchronized boolean isAvailable() { return availableSince != null; } /* * STATIC */ public synchronized static CmsContext 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 ((NodeUserAdmin) getInstance().userAdmin).getAcceptorCredentials(); } private synchronized static void setInstance(CmsContextImpl cmsContextImpl) { if (cmsContextImpl != null) { if (instance.isDone()) throw new IllegalStateException("CMS Context is already set"); instance.complete(cmsContextImpl); } else { instance = new CompletableFuture(); } } private synchronized static CmsContextImpl getInstance() { try { return instance.get(); } catch (InterruptedException | ExecutionException e) { throw new IllegalStateException("Cannot retrieve CMS Context", e); } } }