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