Make CMS production ready
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / kernel / Activator.java
index 1d40c99463c07e58a35ae59b1b900040acc5f7fb..1997b73ce21bd3c58043ef993a2103c9c055a07f 100644 (file)
 package org.argeo.cms.internal.kernel;
 
-import java.util.UUID;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Hashtable;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoLogger;
+import org.argeo.cms.CmsException;
+import org.argeo.node.NodeConstants;
+import org.argeo.node.NodeState;
+import org.argeo.node.RepoConf;
+import org.argeo.util.LangUtils;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
+import org.osgi.service.log.LogReaderService;
 
 /**
  * Activates the {@link Kernel} from the provided {@link BundleContext}. Gives
  * access to kernel information for the rest of the bundle (and only it)
  */
 public class Activator implements BundleActivator {
-       public final static String SYSTEM_KEY_PROPERTY = "argeo.security.systemKey";
+       // public final static String SYSTEM_KEY_PROPERTY =
+       // "argeo.security.systemKey";
        private final Log log = LogFactory.getLog(Activator.class);
 
-       private final static String systemKey;
-       static {
-               systemKey = UUID.randomUUID().toString();
-               System.setProperty(SYSTEM_KEY_PROPERTY, systemKey);
-       }
+       // private final static String systemKey;
+       // static {
+       // System.setProperty(SYSTEM_KEY_PROPERTY, systemKey);
+       // }
+
+//     private static Kernel kernel;
+       private static Activator instance;
+
+       private BundleContext bc;
+       private ConditionalPermissionAdmin permissionAdmin;
+       private LogReaderService logReaderService;
+       private ConfigurationAdmin configurationAdmin;
 
-       private static BundleContext bundleContext;
-       private static Kernel kernel;
+       private NodeLogger logger;
+       private CmsState nodeState;
 
        @Override
-       public void start(BundleContext context) throws Exception {
-               assert bundleContext == null;
-               assert kernel == null;
-               bundleContext = context;
-               try {
-                       kernel = new Kernel();
-                       kernel.init();
-               } catch (Exception e) {
-                       log.error("Cannot boot kernel", e);
+       public void start(BundleContext bundleContext) throws Exception {
+               // try {
+               // kernel = new Kernel();
+               // kernel.init();
+               // } catch (Exception e) {
+               // log.error("Cannot boot kernel", e);
+               // }
+
+               instance = this;
+               this.bc = bundleContext;
+               this.permissionAdmin = getService(ConditionalPermissionAdmin.class);
+               this.logReaderService = getService(LogReaderService.class);
+               this.configurationAdmin = getService(ConfigurationAdmin.class);
+
+               initSecurity();// must be first
+               initArgeoLogger();
+               initNodeState();
+       }
+
+       private void initSecurity() {
+               URL url = getClass().getClassLoader().getResource(KernelConstants.JAAS_CONFIG);
+               System.setProperty("java.security.auth.login.config", url.toExternalForm());
+       }
+
+       private void initArgeoLogger() {
+               logger = new NodeLogger(logReaderService);
+
+               // register
+               bc.registerService(ArgeoLogger.class, logger, null);
+       }
+
+       private void initNodeState() throws IOException {
+               nodeState = new CmsState();
+               bc.registerService(LangUtils.names(NodeState.class, ManagedService.class), nodeState,
+                               LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID));
+
+               Configuration nodeConf = configurationAdmin.getConfiguration(NodeConstants.NODE_STATE_PID);
+               Dictionary<String, Object> props = nodeConf.getProperties();
+               if (props == null) {
+                       if (log.isDebugEnabled())
+                               log.debug("Clean node state");
+                       Dictionary<String, Object> envProps = getStatePropertiesFromEnvironment();
+                       nodeConf.update(envProps);
+               } else {
+                       // Check id state is in line with environment
+                       Dictionary<String, Object> envProps = getStatePropertiesFromEnvironment();
+                       for (String key : LangUtils.keys(envProps)) {
+                               Object envValue = envProps.get(key);
+                               Object storedValue = props.get(key);
+                               if (storedValue == null)
+                                       throw new CmsException("No state value for env " + key + "=" + envValue
+                                                       + ", please clean the OSGi configuration.");
+                               if (!storedValue.equals(envValue))
+                                       throw new CmsException("State value for " + key + "=" + storedValue
+                                                       + " is different from env value =" + envValue + ", please clean the OSGi configuration.");
+                       }
                }
+
        }
 
        @Override
-       public void stop(BundleContext context) throws Exception {
-               kernel.destroy();
-               kernel = null;
-               bundleContext = null;
+       public void stop(BundleContext bundleContext) throws Exception {
+               nodeState.shutdown();
+
+               instance = null;
+               this.bc = null;
+               this.permissionAdmin = null;
+               this.logReaderService = null;
+               this.configurationAdmin = null;
+
+//             if (kernel != null) {
+//                     kernel.destroy();
+//                     kernel = null;
+//             }
+
+       }
+
+       private <T> T getService(Class<T> clazz) {
+               ServiceReference<T> sr = bc.getServiceReference(clazz);
+               if (sr == null)
+                       throw new CmsException("No service available for " + clazz);
+               return bc.getService(sr);
        }
 
-       /**
-        * Singleton interface to the {@link BundleContext} related to the calling
-        * thread.
-        * 
-        * @BundleScope
-        */
-       public static BundleContext getBundleContext() {
-               return bundleContext;
+       protected Dictionary<String, Object> getStatePropertiesFromEnvironment() {
+               Hashtable<String, Object> props = new Hashtable<>();
+               // i18n
+               copyFrameworkProp(NodeConstants.I18N_DEFAULT_LOCALE, props);
+               copyFrameworkProp(NodeConstants.I18N_LOCALES, props);
+               // user admin
+               copyFrameworkProp(NodeConstants.ROLES_URI, props);
+               copyFrameworkProp(NodeConstants.USERADMIN_URIS, props);
+               // data
+               for (RepoConf repoConf : RepoConf.values())
+                       copyFrameworkProp(NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name(), props);
+               // TODO add other environment sources
+               return props;
        }
 
-       public static KernelHeader getKernelHeader() {
-               return kernel;
+       private void copyFrameworkProp(String key, Dictionary<String, Object> props) {
+               String value = bc.getProperty(key);
+               if (value != null)
+                       props.put(key, value);
        }
 
-       /**
-        * @return a String which is guaranteed to be unique between and constant
-        *         within a Java static context (typically a VM launch)
-        * @BundleScope
-        */
-       public final static String getSystemKey() {
-               return systemKey;
+       public static NodeState getNodeState() {
+               return instance.nodeState;
        }
 }