/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bstefanescu */ package org.eclipse.ecr.application; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.naming.NamingException; import org.eclipse.ecr.application.internal.ConfigurationProvider; import org.eclipse.ecr.runtime.api.Framework; import org.eclipse.ecr.runtime.jtajca.NuxeoContainer; import org.eclipse.ecr.runtime.osgi.OSGiRuntimeService; import org.nuxeo.common.Environment; import org.nuxeo.common.jndi.NamingContextFactory; import org.nuxeo.common.utils.Vars; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.ServiceReference; import org.osgi.service.packageadmin.PackageAdmin; /** * This bundle should be put in a startlevel superior than the one used to start nuxeo bundles. * When the bundle is started it will send an application started notification. * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> * */ public class Activator implements BundleActivator, Constants { private static Activator instance; public static Activator getInstance() { return instance; } protected BundleContext context; protected LifeCycleListener[] listeners; protected ServiceReference pkgAdmin; @Override public void start(BundleContext context) throws Exception { this.context = context; instance = this; pkgAdmin = context.getServiceReference(PackageAdmin.class.getName()); // initialize environment Environment.setDefault(createEnvironment()); listeners = loadListeners(); beforeStart(); removeH2Lock(); startJNDI(); startRuntime(); startContainer(); ((OSGiRuntimeService)Framework.getRuntime()).fireApplicationStarted(); // install extra plugins if any installPlugins(); afterStart(); } @Override public void stop(BundleContext context) throws Exception { instance = null; beforeStop(); pkgAdmin = null; this.context = null; afterStop(); listeners = null; } public BundleContext getContext() { return context; } protected LifeCycleListener[] loadListeners() throws Exception { PackageAdmin pa = (PackageAdmin)context.getService(pkgAdmin); try { Bundle[] fragments = pa.getFragments(context.getBundle()); ArrayList<LifeCycleListener> listeners = new ArrayList<LifeCycleListener>(); if (fragments != null) { Bundle bundle = context.getBundle(); for (Bundle fragment : fragments) { String cname = (String)fragment.getHeaders().get(ECR_APPLICATION_LISTENER); if (cname != null) { LifeCycleListener listener = (LifeCycleListener)bundle.loadClass(cname).newInstance(); listener.initialize(context); listeners.add(listener); } } } return listeners.toArray(new LifeCycleListener[listeners.size()]); } finally { context.ungetService(pkgAdmin); } } protected void removeH2Lock() { String h2 = System.getProperty("h2.baseDir"); if (h2 != null) { File file = new File(h2); file = new File(file, "nuxeo.lucene"); file = new File(file, "write.lock"); file.delete(); } } protected void startRuntime() throws BundleException { try { context.getBundle().loadClass("org.eclipse.ecr.runtime.api.Framework"); } catch (Throwable t) { throw new BundleException("Cannot load framework", t); } } protected void startJNDI() throws NamingException { NamingContextFactory.install(); } protected void startContainer() throws NamingException { NuxeoContainer.install(); } protected void beforeStart() throws Exception { for (LifeCycleListener c : listeners) { c.beforeStart(context); } } protected void afterStart() throws Exception { for (LifeCycleListener c : listeners) { c.afterStart(context); } } protected void beforeStop() throws Exception { for (LifeCycleListener c : listeners) { c.beforeStop(context); } } protected void afterStop() throws Exception { for (LifeCycleListener c : listeners) { c.afterStop(context); } } protected Map<String,String> createDefaultConfiguration() { HashMap<String, String> map = new HashMap<String, String>(); map.put(ECR_APP_ID, "default"); map.put(ECR_DATABASE, "h2"); map.put(ECR_HOME_DIR, "${user.home}/.ecr"); map.put(ECR_DATA_DIR, "${"+ECR_HOME_DIR+"}/data"); map.put(ECR_LOG_DIR, "${"+ECR_HOME_DIR+"}/log"); map.put(ECR_CONFIG_URI, "${"+ECR_HOME_DIR+"}/config"); map.put(ECR_CONFIG_PROVIDER, "org.eclipse.ecr.application:"+ConfigurationProvider.class.getName()); return map; } @SuppressWarnings({ "unchecked", "rawtypes" }) protected Environment createEnvironment() throws Exception { // enable OSGi services System.setProperty("ecr.osgi.services", "true"); Map<String,String> vars = createDefaultConfiguration(); String configUri = System.getProperty(ECR_APP_CONFIG); if (configUri != null) { Properties props = loadConfiguration(configUri); vars.putAll((Map)props); } // override using system properties String v = System.getProperty(ECR_APP_ID); if (v != null) { vars.put(ECR_APP_ID, v); } v = System.getProperty(ECR_DATABASE); if (v != null) { vars.put(ECR_DATABASE, v); } v = System.getProperty(ECR_CONFIG_PROVIDER); if (v != null) { vars.put(ECR_CONFIG_PROVIDER, v); } v = System.getProperty(ECR_CONFIG_URI); if (v != null) { vars.put(ECR_CONFIG_URI, v); } v = System.getProperty(ECR_HOME_DIR); if (v != null) { vars.put(ECR_HOME_DIR, v); } v = System.getProperty(ECR_DATA_DIR); if (v != null) { vars.put(ECR_DATA_DIR, v); } v = System.getProperty(ECR_LOG_DIR); if (v != null) { vars.put(ECR_LOG_DIR, v); } // expand properties vars = Vars.expand(vars, new Vars.Resolver() { @Override public String get(String key) { return System.getProperty(key); } }); return createEnvironment(vars); } @SuppressWarnings("unchecked") protected Environment createEnvironment(Map<String,String> vars) throws Exception { String v = vars.get(ECR_HOME_DIR); File home = v == null ? new File(System.getProperty("user.home"), ".ecr") : new File(v); home.mkdirs(); Environment env = new Environment(home); v = vars.get(ECR_DATA_DIR); if (v != null) { env.setData(new File(v)); } v = vars.get(ECR_LOG_DIR); if (v != null) { env.setLog(new File(v)); } env.getData().mkdirs(); env.getLog().mkdirs(); env.getProperties().putAll(vars); String classRef = vars.get(ECR_CONFIG_PROVIDER); if (classRef != null) { env.setConfigurationProvider((Iterable<URL>)newInstance(classRef)); } System.setProperty(ECR_HOME_DIR, home.getAbsolutePath()); System.setProperty(ECR_DATA_DIR, env.getData().getAbsolutePath()); System.setProperty(ECR_LOG_DIR, env.getLog().getAbsolutePath()); return env; } protected static Properties loadConfiguration(String configUri) throws IOException { InputStream in; if (configUri.indexOf(':') != -1) { in = new URL(configUri).openStream(); } else { in = new FileInputStream(new File(configUri)); } try { Properties props = new Properties(); props.load(in); return props; } finally { in.close(); } } public void installPlugins() throws IOException, BundleException { File root = new File(Environment.getDefault().getHome(), "plugins"); if (!root.isDirectory()) { return; } FileIterator plugins = new FileIterator(root, new java.io.FileFilter() { @Override public boolean accept(File pathname) { if (pathname.isDirectory()) { return true; } return pathname.getPath().endsWith(".jar"); } }); plugins.setSkipDirs(true); Bundle[] bundles = context.getBundles(); Map<String,Bundle> installed = new HashMap<String, Bundle>(); for (Bundle bundle : bundles) { installed.put(bundle.getLocation(), bundle); } while (plugins.hasNext()) { File f = plugins.next(); String location = f.getAbsolutePath(); if (!installed.containsKey(location)) { InputStream in = new FileInputStream(f); try { Bundle b = context.installBundle(location, in); b.start(Bundle.START_ACTIVATION_POLICY | Bundle.START_TRANSIENT); } finally { in.close(); } } } } /** * Load a class from another bundle given its reference as <code>bundleSymbolicName:className</code> * If no <code>bundleSymbolicName:</code> prefix is given then a classForName will be done * @param ref * @return */ public Class<?> loadClass(String ref) throws Exception { int i = ref.indexOf(':'); if (i == -1) { return Class.forName(ref); } return loadClass(ref.substring(0, i), ref.substring(i+1)); } public Class<?> loadClass(String bundleName, String className) throws Exception { Bundle bundle = getBundle(bundleName); if (bundle == null) { throw new ClassNotFoundException("No bundle found with name: "+bundleName+". Unable to load class "+className); } return bundle.loadClass(className); } public Object newInstance(String ref) throws Exception { return loadClass(ref).newInstance(); } public Object newInstance(String bundleName, String className) throws Exception { return loadClass(bundleName, className).newInstance(); } public Bundle getBundle(String name) { if (pkgAdmin == null) { return null; } PackageAdmin pa = (PackageAdmin)context.getService(pkgAdmin); Bundle[] bundles = pa.getBundles(name, null); context.ungetService(pkgAdmin); return bundles == null ? null : bundles[0]; } }