/* * 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: * Nuxeo - initial API and implementation * * $Id$ */ package org.eclipse.ecr.runtime; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.ecr.runtime.api.Framework; import org.eclipse.ecr.runtime.model.ComponentInstance; import org.eclipse.ecr.runtime.model.ComponentManager; import org.eclipse.ecr.runtime.model.ComponentName; import org.eclipse.ecr.runtime.model.RuntimeContext; import org.eclipse.ecr.runtime.model.impl.ComponentManagerImpl; import org.eclipse.ecr.runtime.model.impl.DefaultRuntimeContext; import org.nuxeo.common.logging.JavaUtilLoggingHelper; import org.osgi.framework.Bundle; /** * Abstract implementation of the Runtime Service. * <p> * Implementors are encouraged to extend this class instead of directly * implementing the {@link RuntimeService} interface. * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public abstract class AbstractRuntimeService implements RuntimeService { /** * Property that controls whether or not to redirect JUL to JCL. By default * is true (JUL will be redirected) */ public static final String REDIRECT_JUL = "org.eclipse.ecr.runtime.redirectJUL"; private static final Log log = LogFactory.getLog(RuntimeService.class); protected boolean isStarted = false; protected File workingDir; protected Properties properties = new Properties(); protected ComponentManager manager; protected final RuntimeContext context; protected final List<RuntimeExtension> extensions = new ArrayList<RuntimeExtension>(); protected AbstractRuntimeService(DefaultRuntimeContext context) { this(context, null); } // warnings during the deployment. Here are collected all errors occurred // during the startup protected final List<String> warnings = new ArrayList<String>(); protected AbstractRuntimeService(DefaultRuntimeContext context, Map<String, String> properties) { this.context = context; context.setRuntime(this); if (properties != null) { this.properties.putAll(properties); } // get errors set by NuxeoDeployer String errs = System.getProperty("org.eclipse.ecr.runtime.deployment.errors"); if (errs != null) { warnings.addAll(Arrays.asList(errs.split("\n"))); System.clearProperty("org.eclipse.ecr.runtime.deployment.errors"); } } @Override public List<String> getWarnings() { return warnings; } protected ComponentManager createComponentManager() { return new ComponentManagerImpl(this); } protected static URL getBuiltinFeatureURL() { return Thread.currentThread().getContextClassLoader().getResource( "org/nuxeo/runtime/nx-feature.xml"); } @Override public synchronized void start() throws Exception { if (!isStarted) { if (Boolean.parseBoolean(getProperty(REDIRECT_JUL, "true"))) { JavaUtilLoggingHelper.redirectToApacheCommons(); } log.info("Starting Nuxeo Runtime service " + getName() + "; version: " + getVersion()); // NXRuntime.setInstance(this); manager = createComponentManager(); Framework.sendEvent(new RuntimeServiceEvent( RuntimeServiceEvent.RUNTIME_ABOUT_TO_START, this)); doStart(); startExtensions(); isStarted = true; Framework.sendEvent(new RuntimeServiceEvent( RuntimeServiceEvent.RUNTIME_STARTED, this)); } } @Override public synchronized void stop() throws Exception { if (isStarted) { log.info("Stopping Nuxeo Runtime service " + getName() + "; version: " + getVersion()); Framework.sendEvent(new RuntimeServiceEvent( RuntimeServiceEvent.RUNTIME_ABOUT_TO_STOP, this)); stopExtensions(); doStop(); isStarted = false; Framework.sendEvent(new RuntimeServiceEvent( RuntimeServiceEvent.RUNTIME_STOPPED, this)); manager.shutdown(); // NXRuntime.setRuntime(null); manager = null; JavaUtilLoggingHelper.reset(); } } @Override public boolean isStarted() { return isStarted; } protected void doStart() throws Exception { } protected void doStop() throws Exception { } @Override public File getHome() { return workingDir; } public void setHome(File home) { workingDir = home; } @Override public String getDescription() { return toString(); } @Override public Properties getProperties() { return properties; } @Override public String getProperty(String name) { return getProperty(name, null); } @Override public String getProperty(String name, String defValue) { String value = properties.getProperty(name); if (value == null) { value = System.getProperty(name); if (value == null) { return defValue == null ? null : expandVars(defValue); } } return expandVars(value); } public void setProperty(String name, Object value) { properties.put(name, value.toString()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); return sb.append(getName()).append(" version ").append( getVersion().toString()).toString(); } @Override public Object getComponent(String name) { ComponentInstance co = getComponentInstance(name); return co != null ? co.getInstance() : null; } @Override public Object getComponent(ComponentName name) { ComponentInstance co = getComponentInstance(name); return co != null ? co.getInstance() : null; } @Override public ComponentInstance getComponentInstance(String name) { return manager.getComponent(new ComponentName(name)); } @Override public ComponentInstance getComponentInstance(ComponentName name) { return manager.getComponent(name); } @Override public ComponentManager getComponentManager() { return manager; } @Override public RuntimeContext getContext() { return context; } protected void startExtensions() { for (RuntimeExtension ext : extensions) { try { ext.start(); } catch (Exception e) { log.error("Failed to start runtime extension", e); } } } protected void stopExtensions() { for (RuntimeExtension ext : extensions) { try { ext.stop(); } catch (Exception e) { log.error("Failed to start runtime extension", e); } } } @Override public <T> T getService(Class<T> serviceClass) { return manager.getService(serviceClass); } @Override public String expandVars(String expression) { int p = expression.indexOf("${"); if (p == -1) { return expression; // do not expand if not needed } char[] buf = expression.toCharArray(); StringBuilder result = new StringBuilder(buf.length); if (p > 0) { result.append(expression.substring(0, p)); } StringBuilder varBuf = new StringBuilder(); boolean dollar = false; boolean var = false; for (int i = p; i < buf.length; i++) { char c = buf[i]; switch (c) { case '$': dollar = true; break; case '{': if (dollar) { dollar = false; var = true; } break; case '}': if (var) { var = false; String varName = varBuf.toString(); String varValue = getProperty(varName); // get the variable // value if (varValue != null) { result.append(varValue); } else { // let the variable as is result.append("${").append(varName).append('}'); } } break; default: if (var) { varBuf.append(c); } else { result.append(c); } break; } } return result.toString(); } @Override public File getBundleFile(Bundle bundle) { return null; } @Override public Bundle getBundle(String symbolicName) { throw new UnsupportedOperationException("Not implemented"); } }