]> git.argeo.org Git - lgpl/argeo-commons.git/blob - Kernel.java
83f21202e45612855b87d23d29a226479469df3a
[lgpl/argeo-commons.git] / Kernel.java
1 package org.argeo.cms.internal.kernel;
2
3 import java.lang.management.ManagementFactory;
4 import java.net.URL;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 import javax.jcr.Repository;
9 import javax.jcr.RepositoryFactory;
10
11 import org.apache.commons.logging.Log;
12 import org.apache.commons.logging.LogFactory;
13 import org.apache.jackrabbit.util.TransientFileFactory;
14 import org.argeo.ArgeoException;
15 import org.argeo.cms.CmsException;
16 import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
17 import org.argeo.jcr.ArgeoJcrConstants;
18 import org.argeo.security.core.InternalAuthentication;
19 import org.eclipse.equinox.http.servlet.ExtendedHttpService;
20 import org.osgi.framework.BundleContext;
21 import org.osgi.framework.ServiceEvent;
22 import org.osgi.framework.ServiceListener;
23 import org.osgi.framework.ServiceReference;
24 import org.osgi.util.tracker.ServiceTracker;
25 import org.springframework.security.core.context.SecurityContextHolder;
26
27 /**
28 * Argeo CMS Kernel. Responsible for :
29 * <ul>
30 * <li>security</li>
31 * <li>provisioning</li>
32 * <li>transaction</li>
33 * <li>logging</li>
34 * <li>local and remote file systems access</li>
35 * <li>OS access</li>
36 * </ul>
37 */
38 final class Kernel implements ServiceListener {
39 private final static Log log = LogFactory.getLog(Kernel.class);
40
41 private final BundleContext bundleContext = Activator.getBundleContext();
42
43 ThreadGroup threadGroup = new ThreadGroup(Kernel.class.getSimpleName());
44 JackrabbitNode node;
45 OsgiJackrabbitRepositoryFactory repositoryFactory;
46 NodeSecurity nodeSecurity;
47 NodeHttp nodeHttp;
48 private KernelThread kernelThread;
49
50 void init() {
51 URL url = getClass().getClassLoader().getResource(
52 KernelConstants.JAAS_CONFIG);
53 System.setProperty("java.security.auth.login.config",
54 url.toExternalForm());
55
56 ClassLoader currentContextCl = Thread.currentThread()
57 .getContextClassLoader();
58 Thread.currentThread().setContextClassLoader(
59 Kernel.class.getClassLoader());
60 long begin = System.currentTimeMillis();
61 InternalAuthentication initAuth = new InternalAuthentication(
62 KernelConstants.DEFAULT_SECURITY_KEY);
63 SecurityContextHolder.getContext().setAuthentication(initAuth);
64
65 try {
66 // Jackrabbit node
67 node = new JackrabbitNode(bundleContext);
68
69 // JCR repository factory
70 repositoryFactory = new OsgiJackrabbitRepositoryFactory();
71
72 // Authentication
73 nodeSecurity = new NodeSecurity(bundleContext, node);
74
75 // Equinox dependency
76 ExtendedHttpService httpService = waitForHttpService();
77 nodeHttp = new NodeHttp(httpService, node, nodeSecurity);
78
79 // Kernel thread
80 kernelThread = new KernelThread(this);
81 kernelThread.setContextClassLoader(Kernel.class.getClassLoader());
82 kernelThread.start();
83
84 // Publish services to OSGi
85 nodeSecurity.publish();
86 node.publish(repositoryFactory);
87 bundleContext.registerService(RepositoryFactory.class,
88 repositoryFactory, null);
89
90 bundleContext.addServiceListener(Kernel.this);
91 } catch (Exception e) {
92 log.error("Cannot initialize Argeo CMS", e);
93 throw new ArgeoException("Cannot initialize", e);
94 } finally {
95 Thread.currentThread().setContextClassLoader(currentContextCl);
96 }
97
98 long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
99 log.info("## ARGEO CMS UP in " + (jvmUptime / 1000) + "."
100 + (jvmUptime % 1000) + "s ##");
101 long initDuration = System.currentTimeMillis() - begin;
102 if (log.isTraceEnabled())
103 log.trace("Kernel initialization took " + initDuration + "ms");
104 directorsCut(initDuration);
105 }
106
107 void destroy() {
108 long begin = System.currentTimeMillis();
109
110 kernelThread.destroyAndJoin();
111
112 if (nodeHttp != null)
113 nodeHttp.destroy();
114 if (nodeSecurity != null)
115 nodeSecurity.destroy();
116 if (node != null)
117 node.destroy();
118
119 bundleContext.removeServiceListener(this);
120
121 // Clean hanging threads from Jackrabbit
122 TransientFileFactory.shutdown();
123
124 long duration = System.currentTimeMillis() - begin;
125 log.info("## ARGEO CMS DOWN in " + (duration / 1000) + "."
126 + (duration % 1000) + "s ##");
127 }
128
129 @Override
130 public void serviceChanged(ServiceEvent event) {
131 ServiceReference<?> sr = event.getServiceReference();
132 Object jcrRepoAlias = sr
133 .getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
134 if (jcrRepoAlias != null) {// JCR repository
135 String alias = jcrRepoAlias.toString();
136 Repository repository = (Repository) bundleContext.getService(sr);
137 Map<String, Object> props = new HashMap<String, Object>();
138 for (String key : sr.getPropertyKeys())
139 props.put(key, sr.getProperty(key));
140 if (ServiceEvent.REGISTERED == event.getType()) {
141 try {
142 repositoryFactory.register(repository, props);
143 nodeHttp.registerRepositoryServlets(alias, repository);
144 } catch (Exception e) {
145 throw new CmsException("Could not publish JCR repository "
146 + alias, e);
147 }
148 } else if (ServiceEvent.UNREGISTERING == event.getType()) {
149 repositoryFactory.unregister(repository, props);
150 nodeHttp.unregisterRepositoryServlets(alias);
151 }
152 }
153
154 }
155
156 private ExtendedHttpService waitForHttpService() {
157 final ServiceTracker<ExtendedHttpService, ExtendedHttpService> st = new ServiceTracker<ExtendedHttpService, ExtendedHttpService>(
158 bundleContext, ExtendedHttpService.class, null);
159 st.open();
160 ExtendedHttpService httpService;
161 try {
162 httpService = st.waitForService(1000);
163 } catch (InterruptedException e) {
164 httpService = null;
165 }
166
167 if (httpService == null)
168 throw new CmsException("Could not find "
169 + ExtendedHttpService.class + " service.");
170 return httpService;
171 }
172
173 final private static void directorsCut(long initDuration) {
174 // final long ms = 128l + (long) (Math.random() * 128d);
175 long ms = initDuration / 100;
176 log.info("Spend " + ms + "ms"
177 + " reflecting on the progress brought to mankind"
178 + " by Free Software...");
179 long beginNano = System.nanoTime();
180 try {
181 Thread.sleep(ms, 0);
182 } catch (InterruptedException e) {
183 // silent
184 }
185 long durationNano = System.nanoTime() - beginNano;
186 final double M = 1000d * 1000d;
187 double sleepAccuracy = ((double) durationNano) / (ms * M);
188 if (log.isDebugEnabled())
189 log.debug("Sleep accuracy: "
190 + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100))
191 + " %");
192 }
193 }