]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java
Merge branch 'master' of https://mbaudier@code.argeo.org/git/lgpl/argeo-commons.git
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / kernel / Activator.java
1 package org.argeo.cms.internal.kernel;
2
3 import java.io.IOException;
4 import java.net.URL;
5 import java.security.AllPermission;
6 import java.util.Dictionary;
7 import java.util.List;
8 import java.util.Locale;
9 import java.util.concurrent.ExecutorService;
10 import java.util.concurrent.Executors;
11
12 import javax.security.auth.login.Configuration;
13
14 import org.apache.commons.logging.Log;
15 import org.apache.commons.logging.LogFactory;
16 import org.argeo.api.ArgeoLogger;
17 import org.argeo.api.NodeConstants;
18 import org.argeo.api.NodeDeployment;
19 import org.argeo.api.NodeInstance;
20 import org.argeo.api.NodeState;
21 import org.argeo.ident.IdentClient;
22 import org.ietf.jgss.GSSCredential;
23 import org.osgi.framework.Bundle;
24 import org.osgi.framework.BundleActivator;
25 import org.osgi.framework.BundleContext;
26 import org.osgi.framework.Constants;
27 import org.osgi.framework.FrameworkUtil;
28 import org.osgi.service.condpermadmin.BundleLocationCondition;
29 import org.osgi.service.condpermadmin.ConditionInfo;
30 import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
31 import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
32 import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
33 import org.osgi.service.log.LogReaderService;
34 import org.osgi.service.permissionadmin.PermissionInfo;
35 import org.osgi.service.useradmin.UserAdmin;
36 import org.osgi.util.tracker.ServiceTracker;
37
38 /**
39 * Activates the kernel. Gives access to kernel information for the rest of the
40 * bundle (and only it)
41 */
42 public class Activator implements BundleActivator {
43 private final static Log log = LogFactory.getLog(Activator.class);
44
45 private static Activator instance;
46
47 // TODO make it configurable
48 private boolean hardened = false;
49
50 private static BundleContext bundleContext;
51
52 private LogReaderService logReaderService;
53
54 private NodeLogger logger;
55 private CmsState nodeState;
56 private CmsDeployment nodeDeployment;
57 private CmsInstance nodeInstance;
58
59 private ServiceTracker<UserAdmin, NodeUserAdmin> userAdminSt;
60 private ExecutorService internalExecutorService;
61
62 static {
63 Bundle bundle = FrameworkUtil.getBundle(Activator.class);
64 if (bundle != null) {
65 bundleContext = bundle.getBundleContext();
66 }
67 }
68
69 void init() {
70 Runtime.getRuntime().addShutdownHook(new CmsShutdown());
71 instance = this;
72 // this.bc = bundleContext;
73 if (bundleContext != null)
74 this.logReaderService = getService(LogReaderService.class);
75 this.internalExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
76
77 try {
78 initSecurity();
79 initArgeoLogger();
80 initNode();
81
82 if (log.isTraceEnabled())
83 log.trace("Kernel bundle started");
84 } catch (Throwable e) {
85 log.error("## FATAL: CMS activator failed", e);
86 }
87 }
88
89 void destroy() {
90 try {
91 if (nodeInstance != null)
92 nodeInstance.shutdown();
93 if (nodeDeployment != null)
94 nodeDeployment.shutdown();
95 if (nodeState != null)
96 nodeState.shutdown();
97
98 if (userAdminSt != null)
99 userAdminSt.close();
100
101 internalExecutorService.shutdown();
102 instance = null;
103 bundleContext = null;
104 this.logReaderService = null;
105 // this.configurationAdmin = null;
106 } catch (Exception e) {
107 log.error("CMS activator shutdown failed", e);
108 }
109 }
110
111 private void initSecurity() {
112 if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) {
113 String jaasConfig = KernelConstants.JAAS_CONFIG;
114 URL url = getClass().getResource(jaasConfig);
115 // System.setProperty(KernelConstants.JAAS_CONFIG_PROP,
116 // url.toExternalForm());
117 KernelUtils.setJaasConfiguration(url);
118 }
119 // explicitly load JAAS configuration
120 Configuration.getConfiguration();
121
122 // code-level permissions
123 String osgiSecurity = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_SECURITY);
124 if (osgiSecurity != null && Constants.FRAMEWORK_SECURITY_OSGI.equals(osgiSecurity)) {
125 // TODO rather use a tracker?
126 ConditionalPermissionAdmin permissionAdmin = bundleContext
127 .getService(bundleContext.getServiceReference(ConditionalPermissionAdmin.class));
128 if (!hardened) {
129 // All permissions to all bundles
130 ConditionalPermissionUpdate update = permissionAdmin.newConditionalPermissionUpdate();
131 update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
132 new ConditionInfo[] {
133 new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) },
134 new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null) },
135 ConditionalPermissionInfo.ALLOW));
136 // TODO data admin permission
137 // PermissionInfo dataAdminPerm = new PermissionInfo(AuthPermission.class.getName(),
138 // "createLoginContext." + NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, null);
139 // update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
140 // new ConditionInfo[] {
141 // new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) },
142 // new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.DENY));
143 // update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
144 // new ConditionInfo[] {
145 // new ConditionInfo(BundleSignerCondition.class.getName(), new String[] { "CN=\"Eclipse.org Foundation, Inc.\", OU=IT, O=\"Eclipse.org Foundation, Inc.\", L=Nepean, ST=Ontario, C=CA" }) },
146 // new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.ALLOW));
147 update.commit();
148 } else {
149 SecurityProfile securityProfile = new SecurityProfile() {
150 };
151 securityProfile.applySystemPermissions(permissionAdmin);
152 }
153 }
154
155 }
156
157 private void initArgeoLogger() {
158 logger = new NodeLogger(logReaderService);
159 if (bundleContext != null)
160 bundleContext.registerService(ArgeoLogger.class, logger, null);
161 }
162
163 private void initNode() throws IOException {
164 // Node state
165 nodeState = new CmsState();
166 registerService(NodeState.class, nodeState, null);
167
168 // Node deployment
169 nodeDeployment = new CmsDeployment();
170 registerService(NodeDeployment.class, nodeDeployment, null);
171
172 // Node instance
173 nodeInstance = new CmsInstance();
174 registerService(NodeInstance.class, nodeInstance, null);
175 }
176
177 public static <T> void registerService(Class<T> clss, T service, Dictionary<String, ?> properties) {
178 if (bundleContext != null) {
179 bundleContext.registerService(clss, service, properties);
180 }
181
182 }
183
184 public static <T> T getService(Class<T> clss) {
185 if (bundleContext != null) {
186 return bundleContext.getService(bundleContext.getServiceReference(clss));
187 } else {
188 return null;
189 }
190 }
191
192 /*
193 * OSGi
194 */
195
196 @Override
197 public void start(BundleContext bc) throws Exception {
198 if (!bc.getBundle().equals(bundleContext.getBundle()))
199 throw new IllegalStateException(
200 "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle());
201 init();
202 userAdminSt = new ServiceTracker<>(bundleContext, UserAdmin.class, null);
203 userAdminSt.open();
204 }
205
206 @Override
207 public void stop(BundleContext bc) throws Exception {
208 if (!bc.getBundle().equals(bundleContext.getBundle()))
209 throw new IllegalStateException(
210 "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle());
211 destroy();
212 }
213
214 // private <T> T getService(Class<T> clazz) {
215 // ServiceReference<T> sr = bundleContext.getServiceReference(clazz);
216 // if (sr == null)
217 // throw new IllegalStateException("No service available for " + clazz);
218 // return bundleContext.getService(sr);
219 // }
220
221 public static NodeState getNodeState() {
222 return instance.nodeState;
223 }
224
225 public static GSSCredential getAcceptorCredentials() {
226 return getNodeUserAdmin().getAcceptorCredentials();
227 }
228
229 public static boolean isSingleUser() {
230 return getNodeUserAdmin().isSingleUser();
231 }
232
233 public static UserAdmin getUserAdmin() {
234 return (UserAdmin) getNodeUserAdmin();
235 }
236
237 public static String getHttpProxySslHeader() {
238 return KernelUtils.getFrameworkProp(NodeConstants.HTTP_PROXY_SSL_DN);
239 }
240
241 public static IdentClient getIdentClient(String remoteAddr) {
242 if (!IdentClient.isDefaultAuthdPassphraseFileAvailable())
243 return null;
244 // TODO make passphrase more configurable
245 return new IdentClient(remoteAddr);
246 }
247
248 private static NodeUserAdmin getNodeUserAdmin() {
249 NodeUserAdmin res;
250 try {
251 res = instance.userAdminSt.waitForService(60000);
252 } catch (InterruptedException e) {
253 throw new IllegalStateException("Cannot retrieve Node user admin", e);
254 }
255 if (res == null)
256 throw new IllegalStateException("No Node user admin found");
257
258 return res;
259 // ServiceReference<UserAdmin> sr =
260 // instance.bc.getServiceReference(UserAdmin.class);
261 // NodeUserAdmin userAdmin = (NodeUserAdmin) instance.bc.getService(sr);
262 // return userAdmin;
263
264 }
265
266 static ExecutorService getInternalExecutorService() {
267 return instance.internalExecutorService;
268 }
269
270 // static CmsSecurity getCmsSecurity() {
271 // return instance.nodeSecurity;
272 // }
273
274 public String[] getLocales() {
275 // TODO optimize?
276 List<Locale> locales = getNodeState().getLocales();
277 String[] res = new String[locales.size()];
278 for (int i = 0; i < locales.size(); i++)
279 res[i] = locales.get(i).toString();
280 return res;
281 }
282
283 static BundleContext getBundleContext() {
284 return bundleContext;
285 }
286
287 public static void main(String[] args) {
288 instance = new Activator();
289 instance.init();
290 }
291
292 }