/****************************************************************************** * 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.lang.reflect.Method; import java.util.Map; import java.util.Properties; import org.apache.commons.logging.Log; import org.eclipse.gemini.blueprint.test.internal.util.IOUtils; import org.knopflerfish.framework.FrameworkFactoryImpl; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.springframework.beans.BeanUtils; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; /** * Knopflerfish 2.0.4+/3.x Platform. Automatically detects the available version on the class path and uses the * appropriate means to configure and instantiate it. * * @author Costin Leau */ public class KnopflerfishPlatform extends AbstractOsgiPlatform { private static class KF2Platform implements Platform { private static final Class<?> BOOT_CLASS; private static final Constructor<?> CONSTRUCTOR; private static final Method LAUNCH; private static final Method GET_BUNDLE_CONTEXT; private static final Method SHUTDOWN; static { BOOT_CLASS = ClassUtils.resolveClassName(KF_2X_BOOT_CLASS, KF2Platform.class.getClassLoader()); try { CONSTRUCTOR = BOOT_CLASS.getDeclaredConstructor(Object.class); } catch (NoSuchMethodException nsme) { throw new IllegalArgumentException("Invalid framework class", nsme); } LAUNCH = BeanUtils.findDeclaredMethod(BOOT_CLASS, "launch", new Class[] { long.class }); GET_BUNDLE_CONTEXT = org.springframework.util.ReflectionUtils.findMethod(BOOT_CLASS, "getSystemBundleContext"); SHUTDOWN = org.springframework.util.ReflectionUtils.findMethod(BOOT_CLASS, "shutdown"); } private final Object monitor; private Object framework; KF2Platform(Object monitor) { this.monitor = monitor; } public BundleContext start() { framework = BeanUtils.instantiateClass(CONSTRUCTOR, monitor); ReflectionUtils.invokeMethod(LAUNCH, framework, Integer.valueOf(0)); return (BundleContext) ReflectionUtils.invokeMethod(GET_BUNDLE_CONTEXT, framework); } public void stop() { if (framework != null) { ReflectionUtils.invokeMethod(SHUTDOWN, framework); framework = null; } } } private static class KF3Platform implements Platform { private Bundle framework; private final Map properties; private final Log log; private FrameworkTemplate fwkTemplate; KF3Platform(Map properties, Log log) { this.properties = properties; this.log = log; } public BundleContext start() { framework = new FrameworkFactoryImpl().newFramework(properties); fwkTemplate = new DefaultFrameworkTemplate(framework, log); fwkTemplate.init(); fwkTemplate.start(); return framework.getBundleContext(); } public void stop() { if (fwkTemplate != null) { fwkTemplate.stopAndWait(1000); fwkTemplate = null; } } } private static final String KF_2X_BOOT_CLASS = "org.knopflerfish.framework.Framework"; private static final String KF_3X_BOOT_CLASS = "org.knopflerfish.framework.FrameworkContext"; private static final boolean KF_2X = ClassUtils.isPresent(KF_2X_BOOT_CLASS, KnopflerfishPlatform.class.getClassLoader()); private BundleContext context; private Platform framework; private File kfStorageDir; public KnopflerfishPlatform() { toString = "Knopflerfish OSGi Platform"; } Properties getPlatformProperties() { if (kfStorageDir == null) { kfStorageDir = createTempDir("kf"); kfStorageDir.deleteOnExit(); if (log.isDebugEnabled()) log.debug("KF temporary storage dir is " + kfStorageDir.getAbsolutePath()); } // default properties Properties props = new Properties(); props.setProperty("org.osgi.framework.dir", kfStorageDir.getAbsolutePath()); props.setProperty("org.knopflerfish.framework.bundlestorage", "file"); props.setProperty("org.knopflerfish.framework.bundlestorage.file.reference", "true"); props.setProperty("org.knopflerfish.framework.bundlestorage.file.unpack", "false"); props.setProperty("org.knopflerfish.startlevel.use", "true"); props.setProperty("org.knopflerfish.osgi.setcontextclassloader", "true"); // embedded mode props.setProperty("org.knopflerfish.framework.exitonshutdown", "false"); // disable patch CL props.setProperty("org.knopflerfish.framework.patch", "false"); // new in KF 2.0.4 - automatically exports system packages based on the JRE version props.setProperty("org.knopflerfish.framework.system.export.all", "true"); // props.setProperty("org.knopflerfish.framework.system.export.all_15", "true"); // add strict bootpath delegation (introduced in KF 2.3.0) // since otherwise classes will be loaded from the booth classpath // when generating JDK proxies instead of the OSGi space // since KF thinks that a non-OSGi class is making the call. props.setProperty("org.knopflerfish.framework.strictbootclassloading", "true"); return props; } public BundleContext getBundleContext() { return context; } public void start() throws Exception { if (framework == null) { // copy configuration properties to sys properties System.getProperties().putAll(getConfigurationProperties()); framework = (KF_2X ? new KF2Platform(this) : new KF3Platform(getPlatformProperties(), log)); context = framework.start(); } } public void stop() throws Exception { if (framework != null) { context = null; try { framework.stop(); } finally { framework = null; IOUtils.delete(kfStorageDir); } } } }