/****************************************************************************** | |
* Copyright (c) 2006, 2010 VMware Inc. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* and Apache License v2.0 which accompanies this distribution. | |
* The Eclipse Public License is available at | |
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 | |
* is available at http://www.opensource.org/licenses/apache2.0.php. | |
* You may elect to redistribute this code under either of these licenses. | |
* | |
* Contributors: | |
* VMware Inc. | |
*****************************************************************************/ | |
package org.eclipse.gemini.blueprint.test.platform; | |
import java.io.File; | |
import java.lang.reflect.Constructor; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
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.apache.felix.framework.Felix; | |
import org.apache.felix.framework.util.StringMap; | |
import org.apache.felix.main.AutoProcessor; | |
import org.apache.felix.main.Main; | |
import org.eclipse.gemini.blueprint.test.internal.util.IOUtils; | |
import org.osgi.framework.BundleContext; | |
import org.springframework.beans.BeanUtils; | |
import org.springframework.util.ClassUtils; | |
/** | |
* Apache Felix (1.0.3+/1.4.x+/2.0.x) OSGi platform. Automatically detects the available version on the classpath and | |
* uses the appropriate means to configure and instantiate it. | |
* | |
* @author Costin Leau | |
*/ | |
public class FelixPlatform extends AbstractOsgiPlatform { | |
private static abstract class Felix1XPlatform implements Platform { | |
private static final Constructor<?> CTOR; | |
static { | |
Class<?> autoActivator = | |
ClassUtils.resolveClassName("org.apache.felix.main.AutoActivator", Felix1XPlatform.class | |
.getClassLoader()); | |
try { | |
CTOR = autoActivator.getConstructor(Map.class); | |
} catch (Exception ex) { | |
throw new IllegalStateException("Cannot instantiate class " + autoActivator, ex); | |
} | |
} | |
private Felix felix; | |
public final BundleContext start() throws Exception { | |
// load properties | |
Map<String, String> configMap = getConfiguration(); | |
// pass the auto activator as a list | |
List<Object> list = new ArrayList<Object>(1); | |
list.add(BeanUtils.instantiateClass(CTOR, configMap)); | |
felix = createFelix(configMap, list); | |
felix.start(); | |
return felix.getBundleContext(); | |
} | |
public final void stop() throws Exception { | |
felix.stop(); | |
} | |
abstract Felix createFelix(Map<String, String> configMap, List<?> activators) throws Exception; | |
} | |
// private static class Felix10XPlatform extends Felix1XPlatform { | |
// | |
// private static final Constructor<Felix> CTOR; | |
// static { | |
// try { | |
// CTOR = Felix.class.getConstructor(Map.class, List.class); | |
// } catch (NoSuchMethodException ex) { | |
// throw new IllegalStateException("Cannot find Felix constructor", ex); | |
// } | |
// } | |
// | |
// @Override | |
// Felix createFelix(Map<Object, Object> configMap, List<?> activators) throws Exception { | |
// | |
// return CTOR.newInstance(configMap, activators); | |
// } | |
// } | |
// private static class Felix14XPlatform extends Felix1XPlatform { | |
// | |
// @Override | |
// Felix createFelix(Map<Object, Object> configMap, List<?> activators) throws Exception { | |
// configMap.put("felix.systembundle.activators", activators); | |
// return new Felix(configMap); | |
// } | |
// } | |
private static class Felix20XPlatform implements Platform { | |
private FrameworkTemplate fwkTemplate; | |
private final Log log; | |
Felix20XPlatform(Log log) { | |
this.log = log; | |
} | |
public BundleContext start() throws Exception { | |
Map<String, String> configMap = getConfiguration(); | |
Felix fx = new Felix(configMap); | |
fwkTemplate = new DefaultFrameworkTemplate(fx, log); | |
fwkTemplate.init(); | |
BundleContext context = fx.getBundleContext(); | |
AutoProcessor.process(configMap, context); | |
fwkTemplate.start(); | |
return context; | |
} | |
public void stop() throws Exception { | |
fwkTemplate.stopAndWait(1000); | |
} | |
} | |
// private static enum FelixVersion { | |
// V_10X, V_14X, V_20X | |
// } | |
// private static FelixVersion FELIX_VERSION; | |
private static final Log log = LogFactory.getLog(FelixPlatform.class); | |
private static final String FELIX_PROFILE_DIR_PROPERTY = "felix.cache.profiledir"; | |
/** new property in 1.4.0 replacing cache.profiledir */ | |
private static final String OSGI_STORAGE_PROPERTY = "org.osgi.framework.storage"; | |
// static { | |
// ClassLoader loader = Felix.class.getClassLoader(); | |
// detect available Felix version | |
// if (ClassUtils.isPresent("org.apache.felix.main.AutoProcessor", loader)) { | |
// FELIX_VERSION = FelixVersion.V_20X; | |
// } else { | |
// if (ClassUtils.isPresent("org.apache.felix.main.RegularBundleInfo", loader)) { | |
// FELIX_VERSION = FelixVersion.V_14X; | |
// } | |
// FELIX_VERSION = FelixVersion.V_10X; | |
// } | |
// } | |
private BundleContext context; | |
private File felixStorageDir; | |
private Platform platform; | |
public FelixPlatform() { | |
toString = "Felix OSGi Platform"; | |
} | |
Properties getPlatformProperties() { | |
// load Felix configuration | |
Properties props = new Properties(); | |
createStorageDir(props); | |
// disable logging | |
props.put("felix.log.level", "0"); | |
// use embedded mode | |
props.put("felix.embedded.execution", "true"); | |
return props; | |
} | |
public BundleContext getBundleContext() { | |
return context; | |
} | |
/** | |
* Configuration settings for the OSGi test run. | |
* | |
* @return | |
*/ | |
private void createStorageDir(Properties configProperties) { | |
// create a temporary file if none is set | |
if (felixStorageDir == null) { | |
felixStorageDir = createTempDir("felix"); | |
felixStorageDir.deleteOnExit(); | |
if (log.isTraceEnabled()) | |
log.trace("Felix storage dir is " + felixStorageDir.getAbsolutePath()); | |
} | |
configProperties.setProperty(FELIX_PROFILE_DIR_PROPERTY, this.felixStorageDir.getAbsolutePath()); | |
configProperties.setProperty(OSGI_STORAGE_PROPERTY, this.felixStorageDir.getAbsolutePath()); | |
configProperties.setProperty("org.osgi.framework.storage.clean", "onFirstInit"); | |
} | |
public void start() throws Exception { | |
if (platform == null) { | |
// initialize properties and set them as system wide so Felix can pick them up | |
Map<Object, Object> configProperties = getConfigurationProperties(); | |
System.getProperties().putAll(configProperties); | |
platform = new Felix20XPlatform(LogFactory.getLog(Felix20XPlatform.class)); | |
// switch (FELIX_VERSION) { | |
// case V_20X: | |
// platform = new Felix20XPlatform(null); | |
// break; | |
// case V_14X: | |
// platform = new Felix14XPlatform(); | |
// break; | |
// // fallback to 10-12 version | |
// default: | |
// platform = new Felix10XPlatform(); | |
// break; | |
// } | |
context = platform.start(); | |
} | |
} | |
/** | |
* Returns the platform configuration for creating a Felix instance. Uses Felix classes to load and process the | |
* system properties. | |
* | |
* @return Felix configuration | |
*/ | |
private static Map<String, String> getConfiguration() { | |
// Load system properties. | |
Main.loadSystemProperties(); | |
// Read configuration properties. | |
Map<String, String> configProps = Main.loadConfigProperties(); | |
if (configProps == null) { | |
configProps = new HashMap<String, String>(); | |
} | |
// Copy framework properties from the system properties. | |
Main.copySystemProperties(configProps); | |
// Create a (Felix specific) case-insensitive property map | |
// return new StringMap(configProps, false); | |
return configProps; | |
} | |
public void stop() throws Exception { | |
if (platform != null) { | |
try { | |
platform.stop(); | |
} finally { | |
context = null; | |
platform = null; | |
// remove cache folder | |
IOUtils.delete(felixStorageDir); | |
} | |
} | |
} | |
} |