]> git.argeo.org Git - lgpl/argeo-commons.git/blob - CmsDeployment.java
b24fb0a123b40326974a34be0eac92a97bbf94a2
[lgpl/argeo-commons.git] / CmsDeployment.java
1 package org.argeo.cms.internal.kernel;
2
3 import java.io.IOException;
4 import java.lang.management.ManagementFactory;
5 import java.net.URL;
6 import java.util.Dictionary;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10 import org.argeo.api.NodeConstants;
11 import org.argeo.api.NodeDeployment;
12 import org.argeo.api.NodeState;
13 import org.argeo.osgi.transaction.WorkTransaction;
14 import org.argeo.osgi.useradmin.UserAdminConf;
15 import org.eclipse.equinox.http.jetty.JettyConfigurator;
16 import org.osgi.framework.BundleContext;
17 import org.osgi.framework.FrameworkUtil;
18 import org.osgi.framework.ServiceReference;
19 import org.osgi.service.cm.Configuration;
20 import org.osgi.service.cm.ConfigurationAdmin;
21 import org.osgi.service.http.HttpService;
22 import org.osgi.service.useradmin.Group;
23 import org.osgi.service.useradmin.Role;
24 import org.osgi.service.useradmin.UserAdmin;
25 import org.osgi.util.tracker.ServiceTracker;
26
27 /** Implementation of a CMS deployment. */
28 public class CmsDeployment implements NodeDeployment {
29 private final Log log = LogFactory.getLog(getClass());
30 private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
31
32 private DeployConfig deployConfig;
33
34 private Long availableSince;
35
36 // Readiness
37 private boolean nodeAvailable = false;
38 private boolean userAdminAvailable = false;
39 private boolean httpExpected = false;
40 private boolean httpAvailable = false;
41
42 public CmsDeployment() {
43 // ServiceReference<NodeState> nodeStateSr = bc.getServiceReference(NodeState.class);
44 // if (nodeStateSr == null)
45 // throw new CmsException("No node state available");
46
47 // NodeState nodeState = bc.getService(nodeStateSr);
48 // cleanState = nodeState.isClean();
49
50 // nodeHttp = new NodeHttp();
51 initTrackers();
52 }
53
54 private void initTrackers() {
55 ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
56
57 @Override
58 public HttpService addingService(ServiceReference<HttpService> sr) {
59 httpAvailable = true;
60 Object httpPort = sr.getProperty("http.port");
61 Object httpsPort = sr.getProperty("https.port");
62 log.info(httpPortsMsg(httpPort, httpsPort));
63 checkReadiness();
64 return super.addingService(sr);
65 }
66 };
67 // httpSt.open();
68 KernelUtils.asyncOpen(httpSt);
69
70 ServiceTracker<?, ?> userAdminSt = new ServiceTracker<UserAdmin, UserAdmin>(bc, UserAdmin.class, null) {
71 @Override
72 public UserAdmin addingService(ServiceReference<UserAdmin> reference) {
73 UserAdmin userAdmin = super.addingService(reference);
74 addStandardSystemRoles(userAdmin);
75 userAdminAvailable = true;
76 checkReadiness();
77 return userAdmin;
78 }
79 };
80 // userAdminSt.open();
81 KernelUtils.asyncOpen(userAdminSt);
82
83 ServiceTracker<?, ?> confAdminSt = new ServiceTracker<ConfigurationAdmin, ConfigurationAdmin>(bc,
84 ConfigurationAdmin.class, null) {
85 @Override
86 public ConfigurationAdmin addingService(ServiceReference<ConfigurationAdmin> reference) {
87 ConfigurationAdmin configurationAdmin = bc.getService(reference);
88 boolean isClean;
89 try {
90 Configuration[] confs = configurationAdmin
91 .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")");
92 isClean = confs == null || confs.length == 0;
93 } catch (Exception e) {
94 throw new IllegalStateException("Cannot analyse clean state", e);
95 }
96 deployConfig = new DeployConfig(configurationAdmin, isClean);
97 Activator.registerService(NodeDeployment.class, CmsDeployment.this, null);
98 // JcrInitUtils.addToDeployment(CmsDeployment.this);
99 httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null;
100 try {
101 Configuration[] configs = configurationAdmin
102 .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")");
103
104 boolean hasDomain = false;
105 for (Configuration config : configs) {
106 Object realm = config.getProperties().get(UserAdminConf.realm.name());
107 if (realm != null) {
108 log.debug("Found realm: " + realm);
109 hasDomain = true;
110 }
111 }
112 if (hasDomain) {
113 loadIpaJaasConfiguration();
114 }
115 } catch (Exception e) {
116 throw new IllegalStateException("Cannot initialize config", e);
117 }
118 return super.addingService(reference);
119 }
120 };
121 // confAdminSt.open();
122 KernelUtils.asyncOpen(confAdminSt);
123 }
124
125 public void addFactoryDeployConfig(String factoryPid, Dictionary<String, Object> props) {
126 deployConfig.putFactoryDeployConfig(factoryPid, props);
127 deployConfig.save();
128 try {
129 deployConfig.loadConfigs();
130 } catch (IOException e) {
131 throw new IllegalStateException(e);
132 }
133 }
134
135 public Dictionary<String, Object> getProps(String factoryPid, String cn) {
136 return deployConfig.getProps(factoryPid, cn);
137 }
138
139 private String httpPortsMsg(Object httpPort, Object httpsPort) {
140 return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : "");
141 }
142
143 private void addStandardSystemRoles(UserAdmin userAdmin) {
144 // we assume UserTransaction is already available (TODO make it more robust)
145 WorkTransaction userTransaction = bc.getService(bc.getServiceReference(WorkTransaction.class));
146 try {
147 userTransaction.begin();
148 Role adminRole = userAdmin.getRole(NodeConstants.ROLE_ADMIN);
149 if (adminRole == null) {
150 adminRole = userAdmin.createRole(NodeConstants.ROLE_ADMIN, Role.GROUP);
151 }
152 if (userAdmin.getRole(NodeConstants.ROLE_USER_ADMIN) == null) {
153 Group userAdminRole = (Group) userAdmin.createRole(NodeConstants.ROLE_USER_ADMIN, Role.GROUP);
154 userAdminRole.addMember(adminRole);
155 }
156 userTransaction.commit();
157 } catch (Exception e) {
158 try {
159 userTransaction.rollback();
160 } catch (Exception e1) {
161 // silent
162 }
163 throw new IllegalStateException("Cannot add standard system roles", e);
164 }
165 }
166
167 private void loadIpaJaasConfiguration() {
168 if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) {
169 String jaasConfig = KernelConstants.JAAS_CONFIG_IPA;
170 URL url = getClass().getClassLoader().getResource(jaasConfig);
171 KernelUtils.setJaasConfiguration(url);
172 log.debug("Set IPA JAAS configuration.");
173 }
174 }
175
176 public void shutdown() {
177 // if (nodeHttp != null)
178 // nodeHttp.destroy();
179
180 try {
181 JettyConfigurator.stopServer(KernelConstants.DEFAULT_JETTY_SERVER);
182 } catch (Exception e) {
183 log.error("Cannot stop default Jetty server.", e);
184 }
185
186 if (deployConfig != null) {
187 new Thread(() -> deployConfig.save(), "Save Argeo Deploy Config").start();
188 }
189 }
190
191 /**
192 * Checks whether the deployment is available according to expectations, and
193 * mark it as available.
194 */
195 private synchronized void checkReadiness() {
196 if (isAvailable())
197 return;
198 if (nodeAvailable && userAdminAvailable && (httpExpected ? httpAvailable : true)) {
199 String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA);
200 String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA);
201 availableSince = System.currentTimeMillis();
202 long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
203 String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s";
204 log.info("## ARGEO NODE AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##");
205 if (log.isDebugEnabled()) {
206 log.debug("## state: " + state);
207 if (data != null)
208 log.debug("## data: " + data);
209 }
210 long begin = bc.getService(bc.getServiceReference(NodeState.class)).getAvailableSince();
211 long initDuration = System.currentTimeMillis() - begin;
212 if (log.isTraceEnabled())
213 log.trace("Kernel initialization took " + initDuration + "ms");
214 tributeToFreeSoftware(initDuration);
215 }
216 }
217
218 final private void tributeToFreeSoftware(long initDuration) {
219 if (log.isTraceEnabled()) {
220 long ms = initDuration / 100;
221 log.trace("Spend " + ms + "ms" + " reflecting on the progress brought to mankind" + " by Free Software...");
222 long beginNano = System.nanoTime();
223 try {
224 Thread.sleep(ms, 0);
225 } catch (InterruptedException e) {
226 // silent
227 }
228 long durationNano = System.nanoTime() - beginNano;
229 final double M = 1000d * 1000d;
230 double sleepAccuracy = ((double) durationNano) / (ms * M);
231 log.trace("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %");
232 }
233 }
234
235 @Override
236 public synchronized Long getAvailableSince() {
237 return availableSince;
238 }
239
240 public synchronized boolean isAvailable() {
241 return availableSince != null;
242 }
243
244 }