1 package org.argeo.cms.internal.kernel;
2
3 import static java.util.Locale.ENGLISH;
4
5 import java.net.InetAddress;
6 import java.net.UnknownHostException;
7 import java.nio.file.spi.FileSystemProvider;
8 import java.util.ArrayList;
9 import java.util.List;
10 import java.util.Locale;
11
12 import javax.jcr.RepositoryFactory;
13 import javax.transaction.TransactionManager;
14 import javax.transaction.UserTransaction;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.argeo.api.NodeConstants;
19 import org.argeo.api.NodeState;
20 import org.argeo.cms.CmsException;
21 import org.argeo.cms.LocaleUtils;
22 import org.argeo.transaction.simple.SimpleTransactionManager;
23 import org.argeo.util.LangUtils;
24 import org.osgi.framework.BundleContext;
25 import org.osgi.framework.Constants;
26 import org.osgi.framework.FrameworkUtil;
27 import org.osgi.service.cm.ManagedServiceFactory;
28
29 public class CmsState implements NodeState {
30 private final static Log log = LogFactory.getLog(CmsState.class);
31 private final BundleContext bc = FrameworkUtil.getBundle(CmsState.class).getBundleContext();
32
33
34 private Long availableSince;
35
36
37 private Locale defaultLocale;
38 private List<Locale> locales = null;
39
40 private ThreadGroup threadGroup = new ThreadGroup("CMS");
41 private KernelThread kernelThread;
42 private List<Runnable> stopHooks = new ArrayList<>();
43
44 private final String stateUuid;
45
46 private String hostname;
47
48 public CmsState() {
49
50 this.stateUuid = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_UUID);
51
52 try {
53 this.hostname = InetAddress.getLocalHost().getHostName();
54 } catch (UnknownHostException e) {
55 log.error("Cannot set hostname: " + e);
56 }
57
58 availableSince = System.currentTimeMillis();
59 if (log.isDebugEnabled())
60
61
62 log.debug("## CMS starting... (" + stateUuid + ")");
63
64 initI18n();
65 initServices();
66
67
68 kernelThread = new KernelThread(threadGroup, "Kernel Thread");
69 kernelThread.setContextClassLoader(getClass().getClassLoader());
70 kernelThread.start();
71 }
72
73 private void initI18n() {
74 Object defaultLocaleValue = KernelUtils.getFrameworkProp(NodeConstants.I18N_DEFAULT_LOCALE);
75 defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString())
76 : new Locale(ENGLISH.getLanguage());
77 locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(NodeConstants.I18N_LOCALES));
78 }
79
80 private void initServices() {
81
82 String tmType = KernelUtils.getFrameworkProp(NodeConstants.TRANSACTION_MANAGER,
83 NodeConstants.TRANSACTION_MANAGER_SIMPLE);
84 if (NodeConstants.TRANSACTION_MANAGER_SIMPLE.equals(tmType)) {
85 initSimpleTransactionManager();
86 } else if (NodeConstants.TRANSACTION_MANAGER_BITRONIX.equals(tmType)) {
87
88 throw new UnsupportedOperationException(
89 "Bitronix is not supported anymore, but could be again if there is enough interest.");
90 } else {
91 throw new CmsException("Usupported transaction manager type " + tmType);
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 RepositoryServiceFactory repositoryServiceFactory = new RepositoryServiceFactory();
110 stopHooks.add(() -> repositoryServiceFactory.shutdown());
111 bc.registerService(ManagedServiceFactory.class, repositoryServiceFactory,
112 LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_REPOS_FACTORY_PID));
113
114 NodeRepositoryFactory repositoryFactory = new NodeRepositoryFactory();
115 bc.registerService(RepositoryFactory.class, repositoryFactory, null);
116
117
118 NodeUserAdmin userAdmin = new NodeUserAdmin(NodeConstants.ROLES_BASEDN, NodeConstants.TOKENS_BASEDN);
119 stopHooks.add(() -> userAdmin.destroy());
120 bc.registerService(ManagedServiceFactory.class, userAdmin,
121 LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_USER_ADMIN_PID));
122
123
124 CmsFsProvider cmsFsProvider = new CmsFsProvider();
125
126
127
128
129
130
131
132
133
134
135 bc.registerService(FileSystemProvider.class, cmsFsProvider,
136 LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_FS_PROVIDER_PID));
137 }
138
139 private void initSimpleTransactionManager() {
140 SimpleTransactionManager transactionManager = new SimpleTransactionManager();
141 bc.registerService(TransactionManager.class, transactionManager, null);
142 bc.registerService(UserTransaction.class, transactionManager, null);
143
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 void shutdown() {
180 if (log.isDebugEnabled())
181 log.debug("CMS stopping... (" + this.stateUuid + ")");
182
183 if (kernelThread != null)
184 kernelThread.destroyAndJoin();
185
186 Thread stopHookThread = new Thread(() -> applyStopHooks(), "Apply Argeo Stop Hooks");
187 stopHookThread.start();
188 try {
189 stopHookThread.join(10 * 60 * 1000);
190 } catch (InterruptedException e) {
191
192 }
193
194 long duration = ((System.currentTimeMillis() - availableSince) / 1000) / 60;
195 log.info("## ARGEO CMS STOPPED after " + (duration / 60) + "h " + (duration % 60) + "min uptime ##");
196 }
197
198
199 private void applyStopHooks() {
200 for (int i = stopHooks.size() - 1; i >= 0; i--) {
201 try {
202 stopHooks.get(i).run();
203 } catch (Exception e) {
204 log.error("Could not run shutdown hook #" + i);
205 }
206 }
207
208 new GogoShellKiller().start();
209 }
210
211
212
213
214
215
216 @Override
217 public Long getAvailableSince() {
218 return availableSince;
219 }
220
221
222
223
224 public Locale getDefaultLocale() {
225 return defaultLocale;
226 }
227
228 public List<Locale> getLocales() {
229 return locales;
230 }
231
232 public String getHostname() {
233 return hostname;
234 }
235 }