X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FCmsState.java;h=6c97fa14132c6628129e63affccac7c1adb10faa;hb=08490f85954fc85940d1182c12a825b33491c3ba;hp=63aeeac299a42b257ded84f05a6ec3a90e414feb;hpb=10b1584cd1e3550ecdd1d35dded9c4266d1cb4d8;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java index 63aeeac29..6c97fa141 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java @@ -1,46 +1,33 @@ package org.argeo.cms.internal.kernel; -import static bitronix.tm.TransactionManagerServices.getTransactionManager; -import static bitronix.tm.TransactionManagerServices.getTransactionSynchronizationRegistry; import static java.util.Locale.ENGLISH; -import static org.argeo.cms.internal.auth.LocaleChoice.asLocaleList; -import java.io.File; import java.net.InetAddress; import java.net.UnknownHostException; +import java.nio.file.spi.FileSystemProvider; import java.util.ArrayList; -import java.util.Dictionary; -import java.util.Hashtable; import java.util.List; import java.util.Locale; -import java.util.UUID; import javax.jcr.RepositoryFactory; import javax.transaction.TransactionManager; -import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.UserTransaction; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.cms.auth.AuthConstants; -import org.argeo.cms.maintenance.MaintenanceUi; +import org.argeo.cms.CmsException; +import org.argeo.cms.LocaleUtils; import org.argeo.node.NodeConstants; import org.argeo.node.NodeState; +import org.argeo.transaction.simple.SimpleTransactionManager; import org.argeo.util.LangUtils; -import org.eclipse.rap.rwt.application.ApplicationConfiguration; -import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceReference; import org.osgi.service.cm.ManagedServiceFactory; -import bitronix.tm.BitronixTransactionManager; -import bitronix.tm.BitronixTransactionSynchronizationRegistry; -import bitronix.tm.TransactionManagerServices; - public class CmsState implements NodeState { - private final Log log = LogFactory.getLog(CmsState.class); + private final static Log log = LogFactory.getLog(CmsState.class); private final BundleContext bc = FrameworkUtil.getBundle(CmsState.class).getBundleContext(); // REFERENCES @@ -52,7 +39,7 @@ public class CmsState implements NodeState { private ThreadGroup threadGroup = new ThreadGroup("CMS"); private KernelThread kernelThread; - private List shutdownHooks = new ArrayList<>(); + private List stopHooks = new ArrayList<>(); private final String stateUuid; private final boolean cleanState; @@ -65,12 +52,12 @@ public class CmsState implements NodeState { try { this.hostname = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { - log.error("Cannot set hostname", e); + log.error("Cannot set hostname: " + e); } availableSince = System.currentTimeMillis(); if (log.isDebugEnabled()) - log.debug("## CMS STARTED " + this.stateUuid + (cleanState ? " (clean state) " : " ")); + log.debug("## CMS starting... stateUuid=" + this.stateUuid + (cleanState ? " (clean state) " : " ")); initI18n(); initServices(); @@ -85,81 +72,127 @@ public class CmsState implements NodeState { Object defaultLocaleValue = KernelUtils.getFrameworkProp(NodeConstants.I18N_DEFAULT_LOCALE); defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) : new Locale(ENGLISH.getLanguage()); - locales = asLocaleList(KernelUtils.getFrameworkProp(NodeConstants.I18N_LOCALES)); + locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(NodeConstants.I18N_LOCALES)); } private void initServices() { // JTA - initTransactionManager(); + String tmType = KernelUtils.getFrameworkProp(NodeConstants.TRANSACTION_MANAGER, + NodeConstants.TRANSACTION_MANAGER_SIMPLE); + if (NodeConstants.TRANSACTION_MANAGER_SIMPLE.equals(tmType)) { + initSimpleTransactionManager(); + } else if (NodeConstants.TRANSACTION_MANAGER_BITRONIX.equals(tmType)) { +// initBitronixTransactionManager(); + throw new UnsupportedOperationException( + "Bitronix is not supported anymore, but could be again if there is enough interest."); + } else { + throw new CmsException("Usupported transaction manager type " + tmType); + } + + // POI +// POIXMLTypeLoader.setClassLoader(CTConnection.class.getClassLoader()); + + // Tika +// OpenDocumentParser odfParser = new OpenDocumentParser(); +// bc.registerService(Parser.class, odfParser, new Hashtable()); +// PDFParser pdfParser = new PDFParser(); +// bc.registerService(Parser.class, pdfParser, new Hashtable()); +// OOXMLParser ooxmlParser = new OOXMLParser(); +// bc.registerService(Parser.class, ooxmlParser, new Hashtable()); +// TesseractOCRParser ocrParser = new TesseractOCRParser(); +// ocrParser.setLanguage("ara"); +// bc.registerService(Parser.class, ocrParser, new Hashtable()); // JCR RepositoryServiceFactory repositoryServiceFactory = new RepositoryServiceFactory(); - shutdownHooks.add(() -> repositoryServiceFactory.shutdown()); + stopHooks.add(() -> repositoryServiceFactory.shutdown()); bc.registerService(ManagedServiceFactory.class, repositoryServiceFactory, - LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_REPOS_FACTORY_PID)); + LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_REPOS_FACTORY_PID)); NodeRepositoryFactory repositoryFactory = new NodeRepositoryFactory(); bc.registerService(RepositoryFactory.class, repositoryFactory, null); // Security - NodeUserAdmin userAdmin = new NodeUserAdmin(AuthConstants.ROLES_BASEDN); - shutdownHooks.add(() -> userAdmin.destroy()); - Dictionary props = new Hashtable<>(); - props.put(Constants.SERVICE_PID, NodeConstants.NODE_USER_ADMIN_PID); - bc.registerService(ManagedServiceFactory.class, userAdmin, props); - - // UI - bc.registerService(ApplicationConfiguration.class, new MaintenanceUi(), - LangUtils.init(KernelConstants.CONTEXT_NAME_PROP, "system")); - bc.registerService(ApplicationConfiguration.class, new UserUi(), - LangUtils.init(KernelConstants.CONTEXT_NAME_PROP, "user")); + NodeUserAdmin userAdmin = new NodeUserAdmin(NodeConstants.ROLES_BASEDN, NodeConstants.TOKENS_BASEDN); + stopHooks.add(() -> userAdmin.destroy()); + bc.registerService(ManagedServiceFactory.class, userAdmin, + LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_USER_ADMIN_PID)); + + // File System + CmsFsProvider cmsFsProvider = new CmsFsProvider(); +// ServiceLoader fspSl = ServiceLoader.load(FileSystemProvider.class); +// for (FileSystemProvider fsp : fspSl) { +// log.debug("FileSystemProvider " + fsp); +// if (fsp instanceof CmsFsProvider) { +// cmsFsProvider = (CmsFsProvider) fsp; +// } +// } +// for (FileSystemProvider fsp : FileSystemProvider.installedProviders()) { +// log.debug("Installed FileSystemProvider " + fsp); +// } + bc.registerService(FileSystemProvider.class, cmsFsProvider, + LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_FS_PROVIDER_PID)); } - private void initTransactionManager() { - // TODO manage it in a managed service, as startup could be long - ServiceReference existingTm = bc.getServiceReference(TransactionManager.class); - if (existingTm != null) { - if (log.isDebugEnabled()) - log.debug("Using provided transaction manager " + existingTm); - } - bitronix.tm.Configuration tmConf = TransactionManagerServices.getConfiguration(); - tmConf.setServerId(UUID.randomUUID().toString()); - - Bundle bitronixBundle = FrameworkUtil.getBundle(bitronix.tm.Configuration.class); - File tmBaseDir = bitronixBundle.getDataFile(KernelConstants.DIR_TRANSACTIONS); - File tmDir1 = new File(tmBaseDir, "btm1"); - tmDir1.mkdirs(); - tmConf.setLogPart1Filename(new File(tmDir1, tmDir1.getName() + ".tlog").getAbsolutePath()); - File tmDir2 = new File(tmBaseDir, "btm2"); - tmDir2.mkdirs(); - tmConf.setLogPart2Filename(new File(tmDir2, tmDir2.getName() + ".tlog").getAbsolutePath()); - - BitronixTransactionManager transactionManager = getTransactionManager(); - shutdownHooks.add(() -> transactionManager.shutdown()); - BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry = getTransactionSynchronizationRegistry(); - // register + private void initSimpleTransactionManager() { + SimpleTransactionManager transactionManager = new SimpleTransactionManager(); bc.registerService(TransactionManager.class, transactionManager, null); bc.registerService(UserTransaction.class, transactionManager, null); - bc.registerService(TransactionSynchronizationRegistry.class, transactionSynchronizationRegistry, null); - if (log.isDebugEnabled()) - log.debug("Initialised default Bitronix transaction manager"); + // TODO TransactionSynchronizationRegistry } +// private void initBitronixTransactionManager() { +// // TODO manage it in a managed service, as startup could be long +// ServiceReference existingTm = bc.getServiceReference(TransactionManager.class); +// if (existingTm != null) { +// if (log.isDebugEnabled()) +// log.debug("Using provided transaction manager " + existingTm); +// return; +// } +// +// if (!TransactionManagerServices.isTransactionManagerRunning()) { +// bitronix.tm.Configuration tmConf = TransactionManagerServices.getConfiguration(); +// tmConf.setServerId(UUID.randomUUID().toString()); +// +// Bundle bitronixBundle = FrameworkUtil.getBundle(bitronix.tm.Configuration.class); +// File tmBaseDir = bitronixBundle.getDataFile(KernelConstants.DIR_TRANSACTIONS); +// File tmDir1 = new File(tmBaseDir, "btm1"); +// tmDir1.mkdirs(); +// tmConf.setLogPart1Filename(new File(tmDir1, tmDir1.getName() + ".tlog").getAbsolutePath()); +// File tmDir2 = new File(tmBaseDir, "btm2"); +// tmDir2.mkdirs(); +// tmConf.setLogPart2Filename(new File(tmDir2, tmDir2.getName() + ".tlog").getAbsolutePath()); +// } +// BitronixTransactionManager transactionManager = getTransactionManager(); +// stopHooks.add(() -> transactionManager.shutdown()); +// BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry = getTransactionSynchronizationRegistry(); +// // register +// bc.registerService(TransactionManager.class, transactionManager, null); +// bc.registerService(UserTransaction.class, transactionManager, null); +// bc.registerService(TransactionSynchronizationRegistry.class, transactionSynchronizationRegistry, null); +// if (log.isDebugEnabled()) +// log.debug("Initialised default Bitronix transaction manager"); +// } + void shutdown() { - applyShutdownHooks(); + if (log.isDebugEnabled()) + log.debug("CMS stopping... stateUuid=" + this.stateUuid + (cleanState ? " (clean state) " : " ")); if (kernelThread != null) kernelThread.destroyAndJoin(); + // In a different state in order to avois interruptions + new Thread(() -> applyStopHooks(), "Apply Argeo Stop Hooks").start(); + // applyStopHooks(); - if (log.isDebugEnabled()) - log.debug("## CMS STOPPED"); + long duration = ((System.currentTimeMillis() - availableSince) / 1000) / 60; + log.info("## ARGEO CMS STOPPED after " + (duration / 60) + "h " + (duration % 60) + "min uptime ##"); } /** Apply shutdown hoos in reverse order. */ - private void applyShutdownHooks() { - for (int i = shutdownHooks.size() - 1; i >= 0; i--) { + private void applyStopHooks() { + for (int i = stopHooks.size() - 1; i >= 0; i--) { try { - shutdownHooks.get(i).run(); + stopHooks.get(i).run(); } catch (Exception e) { log.error("Could not run shutdown hook #" + i); } @@ -192,62 +225,4 @@ public class CmsState implements NodeState { public String getHostname() { return hostname; } - - /** Workaround for blocking Gogo shell by system shutdown. */ - private class GogoShellKiller extends Thread { - - public GogoShellKiller() { - super("Gogo Shell Killer"); - setDaemon(true); - } - - @Override - public void run() { - ThreadGroup rootTg = getRootThreadGroup(null); - Thread gogoShellThread = findGogoShellThread(rootTg); - if (gogoShellThread == null) - return; - while (getNonDaemonCount(rootTg) > 2) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // silent - } - } - gogoShellThread = findGogoShellThread(rootTg); - if (gogoShellThread == null) - return; - System.exit(0); - } - } - - private static ThreadGroup getRootThreadGroup(ThreadGroup tg) { - if (tg == null) - tg = Thread.currentThread().getThreadGroup(); - if (tg.getParent() == null) - return tg; - else - return getRootThreadGroup(tg.getParent()); - } - - private static int getNonDaemonCount(ThreadGroup rootThreadGroup) { - Thread[] threads = new Thread[rootThreadGroup.activeCount()]; - rootThreadGroup.enumerate(threads); - int nonDameonCount = 0; - for (Thread t : threads) - if (t != null && !t.isDaemon()) - nonDameonCount++; - return nonDameonCount; - } - - private static Thread findGogoShellThread(ThreadGroup rootThreadGroup) { - Thread[] threads = new Thread[rootThreadGroup.activeCount()]; - rootThreadGroup.enumerate(threads, true); - for (Thread thread : threads) { - if (thread.getName().equals("Gogo shell")) - return thread; - } - return null; - } - }