1 package org
.argeo
.cms
.internal
.kernel
;
3 import static bitronix
.tm
.TransactionManagerServices
.getTransactionManager
;
4 import static bitronix
.tm
.TransactionManagerServices
.getTransactionSynchronizationRegistry
;
5 import static java
.util
.Locale
.ENGLISH
;
8 import java
.net
.InetAddress
;
9 import java
.net
.UnknownHostException
;
10 import java
.nio
.file
.spi
.FileSystemProvider
;
11 import java
.util
.ArrayList
;
12 import java
.util
.List
;
13 import java
.util
.Locale
;
14 import java
.util
.UUID
;
16 import javax
.jcr
.RepositoryFactory
;
17 import javax
.transaction
.TransactionManager
;
18 import javax
.transaction
.TransactionSynchronizationRegistry
;
19 import javax
.transaction
.UserTransaction
;
21 import org
.apache
.commons
.logging
.Log
;
22 import org
.apache
.commons
.logging
.LogFactory
;
23 import org
.argeo
.cms
.CmsException
;
24 import org
.argeo
.cms
.i18n
.LocaleUtils
;
25 import org
.argeo
.node
.NodeConstants
;
26 import org
.argeo
.node
.NodeState
;
27 import org
.argeo
.transaction
.simple
.SimpleTransactionManager
;
28 import org
.argeo
.util
.LangUtils
;
29 import org
.osgi
.framework
.Bundle
;
30 import org
.osgi
.framework
.BundleContext
;
31 import org
.osgi
.framework
.Constants
;
32 import org
.osgi
.framework
.FrameworkUtil
;
33 import org
.osgi
.framework
.ServiceReference
;
34 import org
.osgi
.service
.cm
.ManagedServiceFactory
;
36 import bitronix
.tm
.BitronixTransactionManager
;
37 import bitronix
.tm
.BitronixTransactionSynchronizationRegistry
;
38 import bitronix
.tm
.TransactionManagerServices
;
40 public class CmsState
implements NodeState
{
41 private final static Log log
= LogFactory
.getLog(CmsState
.class);
42 private final BundleContext bc
= FrameworkUtil
.getBundle(CmsState
.class).getBundleContext();
45 private Long availableSince
;
48 private Locale defaultLocale
;
49 private List
<Locale
> locales
= null;
51 private ThreadGroup threadGroup
= new ThreadGroup("CMS");
52 private KernelThread kernelThread
;
53 private List
<Runnable
> stopHooks
= new ArrayList
<>();
55 private final String stateUuid
;
56 private final boolean cleanState
;
57 private String hostname
;
59 public CmsState(String stateUuid
) {
60 this.stateUuid
= stateUuid
;
61 String frameworkUuid
= KernelUtils
.getFrameworkProp(Constants
.FRAMEWORK_UUID
);
62 this.cleanState
= stateUuid
.equals(frameworkUuid
);
64 this.hostname
= InetAddress
.getLocalHost().getHostName();
65 } catch (UnknownHostException e
) {
66 log
.error("Cannot set hostname: " + e
);
69 availableSince
= System
.currentTimeMillis();
70 if (log
.isDebugEnabled())
71 log
.debug("## CMS starting... stateUuid=" + this.stateUuid
+ (cleanState ?
" (clean state) " : " "));
77 kernelThread
= new KernelThread(threadGroup
, "Kernel Thread");
78 kernelThread
.setContextClassLoader(getClass().getClassLoader());
82 private void initI18n() {
83 Object defaultLocaleValue
= KernelUtils
.getFrameworkProp(NodeConstants
.I18N_DEFAULT_LOCALE
);
84 defaultLocale
= defaultLocaleValue
!= null ?
new Locale(defaultLocaleValue
.toString())
85 : new Locale(ENGLISH
.getLanguage());
86 locales
= LocaleUtils
.asLocaleList(KernelUtils
.getFrameworkProp(NodeConstants
.I18N_LOCALES
));
89 private void initServices() {
91 String tmType
= KernelUtils
.getFrameworkProp(NodeConstants
.TRANSACTION_MANAGER
,
92 NodeConstants
.TRANSACTION_MANAGER_SIMPLE
);
93 if (NodeConstants
.TRANSACTION_MANAGER_SIMPLE
.equals(tmType
)) {
94 initSimpleTransactionManager();
95 } else if (NodeConstants
.TRANSACTION_MANAGER_BITRONIX
.equals(tmType
)) {
96 initBitronixTransactionManager();
98 throw new CmsException("Usupported transaction manager type " + tmType
);
102 RepositoryServiceFactory repositoryServiceFactory
= new RepositoryServiceFactory();
103 stopHooks
.add(() -> repositoryServiceFactory
.shutdown());
104 bc
.registerService(ManagedServiceFactory
.class, repositoryServiceFactory
,
105 LangUtils
.dico(Constants
.SERVICE_PID
, NodeConstants
.NODE_REPOS_FACTORY_PID
));
107 NodeRepositoryFactory repositoryFactory
= new NodeRepositoryFactory();
108 bc
.registerService(RepositoryFactory
.class, repositoryFactory
, null);
111 NodeUserAdmin userAdmin
= new NodeUserAdmin(NodeConstants
.ROLES_BASEDN
);
112 stopHooks
.add(() -> userAdmin
.destroy());
113 bc
.registerService(ManagedServiceFactory
.class, userAdmin
,
114 LangUtils
.dico(Constants
.SERVICE_PID
, NodeConstants
.NODE_USER_ADMIN_PID
));
117 CmsFsProvider cmsFsProvider
= new CmsFsProvider();
118 bc
.registerService(FileSystemProvider
.class, cmsFsProvider
,
119 LangUtils
.dico(Constants
.SERVICE_PID
, NodeConstants
.NODE_FS_PROVIDER_PID
));
122 private void initSimpleTransactionManager() {
123 SimpleTransactionManager transactionManager
= new SimpleTransactionManager();
124 bc
.registerService(TransactionManager
.class, transactionManager
, null);
125 bc
.registerService(UserTransaction
.class, transactionManager
, null);
126 // TODO TransactionSynchronizationRegistry
129 private void initBitronixTransactionManager() {
130 // TODO manage it in a managed service, as startup could be long
131 ServiceReference
<TransactionManager
> existingTm
= bc
.getServiceReference(TransactionManager
.class);
132 if (existingTm
!= null) {
133 if (log
.isDebugEnabled())
134 log
.debug("Using provided transaction manager " + existingTm
);
138 if (!TransactionManagerServices
.isTransactionManagerRunning()) {
139 bitronix
.tm
.Configuration tmConf
= TransactionManagerServices
.getConfiguration();
140 tmConf
.setServerId(UUID
.randomUUID().toString());
142 Bundle bitronixBundle
= FrameworkUtil
.getBundle(bitronix
.tm
.Configuration
.class);
143 File tmBaseDir
= bitronixBundle
.getDataFile(KernelConstants
.DIR_TRANSACTIONS
);
144 File tmDir1
= new File(tmBaseDir
, "btm1");
146 tmConf
.setLogPart1Filename(new File(tmDir1
, tmDir1
.getName() + ".tlog").getAbsolutePath());
147 File tmDir2
= new File(tmBaseDir
, "btm2");
149 tmConf
.setLogPart2Filename(new File(tmDir2
, tmDir2
.getName() + ".tlog").getAbsolutePath());
151 BitronixTransactionManager transactionManager
= getTransactionManager();
152 stopHooks
.add(() -> transactionManager
.shutdown());
153 BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry
= getTransactionSynchronizationRegistry();
155 bc
.registerService(TransactionManager
.class, transactionManager
, null);
156 bc
.registerService(UserTransaction
.class, transactionManager
, null);
157 bc
.registerService(TransactionSynchronizationRegistry
.class, transactionSynchronizationRegistry
, null);
158 if (log
.isDebugEnabled())
159 log
.debug("Initialised default Bitronix transaction manager");
163 if (log
.isDebugEnabled())
164 log
.debug("CMS stopping... stateUuid=" + this.stateUuid
+ (cleanState ?
" (clean state) " : " "));
166 if (kernelThread
!= null)
167 kernelThread
.destroyAndJoin();
168 // In a different state in order to avois interruptions
169 new Thread(() -> applyStopHooks(), "Apply Argeo Stop Hooks").start();
172 long duration
= ((System
.currentTimeMillis() - availableSince
) / 1000) / 60;
173 log
.info("## ARGEO CMS STOPPED after " + (duration
/ 60) + "h " + (duration
% 60) + "min uptime ##");
176 /** Apply shutdown hoos in reverse order. */
177 private void applyStopHooks() {
178 for (int i
= stopHooks
.size() - 1; i
>= 0; i
--) {
180 stopHooks
.get(i
).run();
181 } catch (Exception e
) {
182 log
.error("Could not run shutdown hook #" + i
);
185 // Clean hanging Gogo shell thread
186 new GogoShellKiller().start();
190 public boolean isClean() {
195 public Long
getAvailableSince() {
196 return availableSince
;
202 public Locale
getDefaultLocale() {
203 return defaultLocale
;
206 public List
<Locale
> getLocales() {
210 public String
getHostname() {