Mercurial > hg > release > thermostat-0.6
changeset 906:b1b81446c892
Merge bundles/launcher plug-ins.
Here is a patch which merges classes which used to be in the bundles plug-in
into the launcher plug-in. I don't see why this splitting is useful any longer.
Now we have the "main" jar which fires up the framework and uses the launcher
plug-in to do the osgi-based launching. This is a first step to clean up
dependencies amongst bundles which should eventually lead to cleaner dep-trees
and common-core not depend on storage-core any longer, having this c.r.t.test
package removed from common-core etc.
ThermostatTest was also largely commented out. The only non-comment part was
the setup routine. A few basic tests have been reinstated.
Reviewed-by: vanaltj
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-January/005093.html
line wrap: on
line diff
--- a/bundles/pom.xml Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - Copyright 2012 Red Hat, Inc. - - This file is part of Thermostat. - - Thermostat is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your - option) any later version. - - Thermostat is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Thermostat; see the file COPYING. If not see - <http://www.gnu.org/licenses />. - - Linking this code with other modules is making a combined work - based on this code. Thus, the terms and conditions of the GNU - General Public License cover the whole combination. - - As a special exception, the copyright holders of this code give - you permission to link this code with independent modules to - produce an executable, regardless of the license terms of these - independent modules, and to copy and distribute the resulting - executable under terms of your choice, provided that you also - meet, for each linked independent module, the terms and conditions - of the license of that module. An independent module is a module - which is not derived from or based on this code. If you modify - this code, you may extend this exception to your version of the - library, but you are not obligated to do so. If you do not wish - to do so, delete this exception statement from your version. - ---> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>com.redhat.thermostat</groupId> - <artifactId>thermostat</artifactId> - <version>0.5.0-SNAPSHOT</version> - </parent> - - <artifactId>thermostat-bundles</artifactId> - <packaging>bundle</packaging> - - <name>Service providing entry point to OSGi-land</name> - - <dependencies> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-api-mockito</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-module-junit4</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.jboss.netty</groupId> - <artifactId>netty</artifactId> - </dependency> - <dependency> - <groupId>org.osgi</groupId> - <artifactId>org.osgi.core</artifactId> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>com.redhat.thermostat</groupId> - <artifactId>thermostat-common-core</artifactId> - <version>${project.version}</version> - <type>jar</type> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-bundle-plugin</artifactId> - <extensions>true</extensions> - <configuration> - <instructions> - <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor> - <Bundle-Activator>com.redhat.thermostat.bundles.impl.Activator</Bundle-Activator> - <Bundle-SymbolicName>com.redhat.thermostat.bundles.core</Bundle-SymbolicName> - <Export-Package> - com.redhat.thermostat.bundles - </Export-Package> - <Private-Package> - com.redhat.thermostat.bundles.impl - </Private-Package> - <!-- Do not autogenerate uses clauses in Manifests --> - <_nouses>true</_nouses> - </instructions> - </configuration> - </plugin> - </plugins> - </build> -</project>
--- a/bundles/src/main/java/com/redhat/thermostat/bundles/OSGiRegistry.java Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.bundles; - -import java.io.IOException; -import java.util.List; - -import org.osgi.framework.BundleException; -import org.osgi.framework.launch.Framework; - -import com.redhat.thermostat.bundles.impl.BundleLoader; -import com.redhat.thermostat.common.Configuration; -import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; -import com.redhat.thermostat.common.cli.CommandInfoSource; - -/** - * A Service that provides features to load bundles for given command names. - */ -public abstract class OSGiRegistry { - - public abstract void setPrintOSGiInfo(boolean printOSGiInfo); - - public abstract void setCommandInfoSource(CommandInfoSource source); - - public abstract void addBundlesFor(String commandName) throws BundleException, CommandInfoNotFoundException, IOException; - - public static void preLoadBundles(Framework framework, List<String> bundleLocations, - boolean printOSGiInfo) throws BundleException { - BundleLoader loader = new BundleLoader(printOSGiInfo); - loader.installAndStartBundles(framework, bundleLocations); - } - - public abstract Configuration getConfiguration(); - -}
--- a/bundles/src/main/java/com/redhat/thermostat/bundles/impl/Activator.java Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.bundles.impl; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - -import com.redhat.thermostat.bundles.OSGiRegistry; -import com.redhat.thermostat.common.Configuration; - -public class Activator implements BundleActivator { - - ServiceRegistration reg; - - @Override - public void start(BundleContext context) throws Exception { - OSGiRegistryImpl bundleRegistry = new OSGiRegistryImpl(new Configuration()); - reg = context.registerService(OSGiRegistry.class.getName(), bundleRegistry, null); - } - - @Override - public void stop(BundleContext context) throws Exception { - if (reg != null) { - reg.unregister(); - reg = null; - } - } - -}
--- a/bundles/src/main/java/com/redhat/thermostat/bundles/impl/BundleLoader.java Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.bundles.impl; - -import java.util.ArrayList; -import java.util.List; - -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.Constants; -import org.osgi.framework.launch.Framework; - -public class BundleLoader { - - private boolean printOSGiInfo = false; - - BundleLoader() { - this(false); - } - - public BundleLoader(boolean printOSGiInfo) { - setPrintOSGiInfo(printOSGiInfo); - } - - public void setPrintOSGiInfo(boolean printOSGiInfo) { - this.printOSGiInfo = printOSGiInfo; - } - - public List<Bundle> installAndStartBundles(Framework framework, - List<String>bundleLocations) throws BundleException { - List<Bundle> bundles = new ArrayList<>(); - BundleContext ctx = framework.getBundleContext(); - for (String location : bundleLocations) { - Bundle bundle = ctx.installBundle(location); - if (printOSGiInfo) { - System.out.println("BundleLoader: installed bundle: \"" + - location + "\" as id " + bundle.getBundleId()); - } - bundles.add(bundle); - } - startBundles(bundles); - return bundles; - } - - private void startBundles(List<Bundle> bundles) throws BundleException { - for (Bundle bundle : bundles) { - - if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) { - if (printOSGiInfo) { - System.out.println("BundleLoader: bundle \"" + bundle.getBundleId() + "\" is a fragment; not starting it"); - } - continue; - } - - if (printOSGiInfo) { - System.out.println("BundleLoader: starting bundle: \"" + bundle.getBundleId() + "\""); - } - // We don't want for the framework to set the auto-start bit. Thus, passing - // START_TRANSIENT explicitly - bundle.start(Bundle.START_TRANSIENT); - } - } - -}
--- a/bundles/src/main/java/com/redhat/thermostat/bundles/impl/OSGiRegistryImpl.java Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.bundles.impl; - -import com.redhat.thermostat.bundles.OSGiRegistry; -import com.redhat.thermostat.common.Configuration; -import com.redhat.thermostat.common.ConfigurationException; -import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; -import com.redhat.thermostat.common.cli.CommandInfoSource; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleException; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.launch.Framework; - -public class OSGiRegistryImpl extends OSGiRegistry { - - private CommandInfoSource commandInfos; - private Map<String, Bundle> loaded; - private Configuration configuration; - private BundleLoader loader; - - OSGiRegistryImpl(Configuration configuration) throws ConfigurationException, FileNotFoundException, IOException { - initLoadedBundles(); - this.configuration = configuration; - loader = new BundleLoader(configuration.getPrintOSGiInfo()); - } - - private void initLoadedBundles() { - loaded = new HashMap<>(); - Framework framework = getFramework(this.getClass()); - for (Bundle bundle: framework.getBundleContext().getBundles()) { - loaded.put(bundle.getLocation(), bundle); - } - } - - @Override - public void setPrintOSGiInfo(boolean printOSGiInfo) { - configuration.setPrintOSGiInfo(printOSGiInfo); - loader.setPrintOSGiInfo(printOSGiInfo); - } - - @Override - public void setCommandInfoSource(CommandInfoSource source) { - this.commandInfos = source; - } - - @Override - public void addBundlesFor(String commandName) throws BundleException, IOException, CommandInfoNotFoundException { - if (configuration.getPrintOSGiInfo()) { - System.out.println("Loading additional bundles for: " + commandName); - } - List<String> requiredBundles = commandInfos.getCommandInfo(commandName).getDependencyResourceNames(); - List<String> bundlesToLoad = new ArrayList<>(); - if (requiredBundles != null) { - for (String resource : requiredBundles) { - if (!isBundleActive(resource)) { - bundlesToLoad.add(resource); - } - } - } - Framework framework = getFramework(this.getClass()); - List<Bundle> successBundles = loader.installAndStartBundles(framework, bundlesToLoad); - for (Bundle bundle : successBundles) { - loaded.put(bundle.getLocation(), bundle); - } - } - - private boolean isBundleActive(String location) { - Bundle bundle = loaded.get(location); - return (bundle != null) && (bundle.getState() == Bundle.ACTIVE); - } - - private Framework getFramework(Class<?> cls) { - return (Framework) FrameworkUtil.getBundle(cls).getBundleContext().getBundle(0); - } - - @Override - public Configuration getConfiguration() { - return configuration; - } -}
--- a/bundles/src/test/java/com/redhat/thermostat/bundles/OSGiRegistryTest.java Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.bundles; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.whenNew; - -import java.util.ArrayList; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.osgi.framework.launch.Framework; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import com.redhat.thermostat.bundles.impl.BundleLoader; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(OSGiRegistry.class) -public class OSGiRegistryTest { - - @Test - public void testPreLoadBundles() throws Exception { - Framework framework = mock(Framework.class); - ArrayList<String> bundleLocations = new ArrayList<>(); - BundleLoader loader = mock(BundleLoader.class); - whenNew(BundleLoader.class).withParameterTypes(Boolean.TYPE). - withArguments(any()).thenReturn(loader); - - OSGiRegistry.preLoadBundles(framework, bundleLocations, true); - verify(loader).installAndStartBundles(framework, bundleLocations); - } -}
--- a/bundles/src/test/java/com/redhat/thermostat/bundles/impl/BundleLoaderTest.java Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.bundles.impl; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.Arrays; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.List; - -import org.junit.Test; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.Constants; -import org.osgi.framework.launch.Framework; - -import com.redhat.thermostat.test.Bug; - -public class BundleLoaderTest { - - @Test - public void verifyBundlesAreInstalledAndStarted() throws BundleException { - final String BUNDLE_LOCATION = "bundle-location-1"; - - Bundle bundle = mock(Bundle.class); - when(bundle.getHeaders()).thenReturn(new Hashtable<>()); - BundleContext bundleContext = mock(BundleContext.class); - when(bundleContext.installBundle(BUNDLE_LOCATION)).thenReturn(bundle); - Framework framework = mock(Framework.class); - when(framework.getBundleContext()).thenReturn(bundleContext); - List<String> bundleLocations = Arrays.asList(BUNDLE_LOCATION); - - BundleLoader loader = new BundleLoader(); - loader.installAndStartBundles(framework, bundleLocations); - - verify(bundle).start(Bundle.START_TRANSIENT); - } - - @Bug(id="1227", - summary="Make sure launcher does not start fragments", - url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1227") - @Test - public void verifyFragmentsAreInstalledButNotStarted() throws BundleException { - final String BUNDLE_LOCATION = "bundle-location-1"; - - Bundle bundle = mock(Bundle.class); - Dictionary<String, String> bundleHeaders = new Hashtable<>(); - bundleHeaders.put(Constants.FRAGMENT_HOST, "foo-bar"); - when(bundle.getHeaders()).thenReturn(bundleHeaders); - - BundleContext bundleContext = mock(BundleContext.class); - when(bundleContext.installBundle(BUNDLE_LOCATION)).thenReturn(bundle); - Framework framework = mock(Framework.class); - when(framework.getBundleContext()).thenReturn(bundleContext); - List<String> bundleLocations = Arrays.asList(BUNDLE_LOCATION); - - BundleLoader loader = new BundleLoader(); - loader.installAndStartBundles(framework, bundleLocations); - - verify(bundle, times(0)).start(Bundle.START_TRANSIENT); - - } -}
--- a/bundles/src/test/java/com/redhat/thermostat/bundles/impl/OSGiRegistryImplTest.java Thu Jan 10 21:48:04 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.bundles.impl; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.whenNew; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.launch.Framework; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import com.redhat.thermostat.common.Configuration; -import com.redhat.thermostat.common.cli.CommandInfo; -import com.redhat.thermostat.common.cli.CommandInfoSource; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({OSGiRegistryImpl.class, FrameworkUtil.class}) -public class OSGiRegistryImplTest { - - private static final String cmdName = "one"; - - private static final String jar1Name = "/one.jar"; - private static final String jar2Name = "/two.jar"; - private static final String jar3Name = "/three.jar"; - - private Bundle b1, b2, b3; - private List<String> bundleLocs; - - private BundleLoader loader; - private Configuration conf; - - @Before - public void setUp() throws Exception { - conf = mock(Configuration.class); - when(conf.getThermostatHome()).thenReturn("no_matter"); - bundleLocs = Arrays.asList(jar1Name, jar2Name, jar3Name); - b1 = mock(Bundle.class); - when(b1.getLocation()).thenReturn(jar1Name); - when(b1.getState()).thenReturn(Bundle.ACTIVE); - b2 = mock(Bundle.class); - when(b2.getLocation()).thenReturn(jar2Name); - when(b2.getState()).thenReturn(Bundle.ACTIVE); - b3 = mock(Bundle.class); - when(b3.getLocation()).thenReturn(jar3Name); - when(b3.getState()).thenReturn(Bundle.ACTIVE); - List<Bundle> installed = Arrays.asList(b1, b2, b3); - - loader = mock(BundleLoader.class); - when(loader.installAndStartBundles(any(Framework.class), eq(bundleLocs))). - thenReturn(installed); - whenNew(BundleLoader.class).withParameterTypes(Boolean.TYPE). - withArguments(any()).thenReturn(loader); - } - - @Test - public void testLoadBundlesFor() throws Exception { - verifyBundlesLoaded(new Bundle[] {}, bundleLocs); - } - - @Test - public void verifyAlreadyLoadedBundlesNotReloaded() throws Exception { - verifyBundlesLoaded(new Bundle[] {b1, b2}, Arrays.asList(jar3Name)); - } - - private void verifyBundlesLoaded(Bundle[] preloaded, List<String> locationsNeeded) throws Exception { - Bundle theBundle = b2; - BundleContext theContext = mock(BundleContext.class); - when(theContext.getBundles()).thenReturn(preloaded); - Framework theFramework = mock(Framework.class); - when(theFramework.getBundleContext()).thenReturn(theContext); - when(theContext.getBundle(0)).thenReturn(theFramework); - when(theBundle.getBundleContext()).thenReturn(theContext); - mockStatic(FrameworkUtil.class); - when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); - - OSGiRegistryImpl registry = new OSGiRegistryImpl(conf); - CommandInfoSource infos = mock(CommandInfoSource.class); - CommandInfo info = mock(CommandInfo.class); - when (info.getDependencyResourceNames()).thenReturn(bundleLocs); - when (infos.getCommandInfo(cmdName)).thenReturn(info); - registry.setCommandInfoSource(infos); - registry.addBundlesFor(cmdName); - verify(loader).installAndStartBundles(any(Framework.class), eq(locationsNeeded)); - } - - @Test - public void verifySetOSGiVerbosityByReflection() throws Exception { - - // All this fluff is just so constructor doesn't NPE. - Bundle theBundle = b2; - BundleContext theContext = mock(BundleContext.class); - when(theContext.getBundles()).thenReturn(new Bundle[]{}); - Framework theFramework = mock(Framework.class); - when(theFramework.getBundleContext()).thenReturn(theContext); - when(theContext.getBundle(0)).thenReturn(theFramework); - when(theBundle.getBundleContext()).thenReturn(theContext); - mockStatic(FrameworkUtil.class); - when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); - - Object registry = new OSGiRegistryImpl(conf); - Class clazz = registry.getClass(); - Method m = clazz.getMethod("setPrintOSGiInfo", Boolean.TYPE); - m.invoke(registry, true); // If this fails, then API has changed in ways that break FrameworkProvider. - } - -}
--- a/distribution/pom.xml Thu Jan 10 21:48:04 2013 +0100 +++ b/distribution/pom.xml Thu Jan 10 16:16:29 2013 +0100 @@ -322,11 +322,6 @@ </dependency> <dependency> <groupId>com.redhat.thermostat</groupId> - <artifactId>thermostat-bundles</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-launcher</artifactId> <version>${project.version}</version> </dependency>
--- a/launcher/pom.xml Thu Jan 10 21:48:04 2013 +0100 +++ b/launcher/pom.xml Thu Jan 10 16:16:29 2013 +0100 @@ -110,11 +110,6 @@ </dependency> <dependency> <groupId>com.redhat.thermostat</groupId> - <artifactId>thermostat-bundles</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-common-test</artifactId> <version>${project.version}</version> <scope>test</scope>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/BundleManager.java Thu Jan 10 16:16:29 2013 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.launcher; + +import java.io.IOException; +import java.util.List; + +import org.osgi.framework.BundleException; +import org.osgi.framework.launch.Framework; + +import com.redhat.thermostat.common.Configuration; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; +import com.redhat.thermostat.common.cli.CommandInfoSource; +import com.redhat.thermostat.launcher.internal.BundleLoader; + +/** + * A Service that provides features to load bundles for given command names. + */ +public abstract class BundleManager { + + public abstract void setPrintOSGiInfo(boolean printOSGiInfo); + + public abstract void setCommandInfoSource(CommandInfoSource source); + + public abstract void addBundlesFor(String commandName) throws BundleException, CommandInfoNotFoundException, IOException; + + public static void preLoadBundles(Framework framework, List<String> bundleLocations, + boolean printOSGiInfo) throws BundleException { + BundleLoader loader = new BundleLoader(printOSGiInfo); + loader.installAndStartBundles(framework, bundleLocations); + } + + public abstract Configuration getConfiguration(); + +}
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java Thu Jan 10 21:48:04 2013 +0100 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java Thu Jan 10 16:16:29 2013 +0100 @@ -36,70 +36,85 @@ package com.redhat.thermostat.launcher.internal; -import java.util.Map; - import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; -import com.redhat.thermostat.bundles.OSGiRegistry; import com.redhat.thermostat.common.CommandLoadingBundleActivator; -import com.redhat.thermostat.common.MultipleServiceTracker; -import com.redhat.thermostat.common.MultipleServiceTracker.Action; +import com.redhat.thermostat.common.Configuration; import com.redhat.thermostat.common.cli.CommandContextFactory; import com.redhat.thermostat.common.cli.CommandInfoSource; +import com.redhat.thermostat.launcher.BundleManager; import com.redhat.thermostat.launcher.Launcher; import com.redhat.thermostat.utils.keyring.Keyring; public class Activator extends CommandLoadingBundleActivator { + + @SuppressWarnings({"rawtypes", "unchecked"}) + class RegisterLauncherCustomizer implements ServiceTrackerCustomizer { - class RegisterLauncherAction implements Action { - + private ServiceRegistration launcherReg; + private ServiceRegistration bundleManReg; + private ServiceRegistration cmdInfoReg; private BundleContext context; - private ServiceReference registryReference; + private BundleManager bundleService; - RegisterLauncherAction(BundleContext context) { + RegisterLauncherCustomizer(BundleContext context, BundleManager bundleService) { this.context = context; + this.bundleService = bundleService; } @Override - public void dependenciesAvailable(Map<String, Object> services) { - - registryReference = context.getServiceReference(OSGiRegistry.class); - OSGiRegistry bundleService = (OSGiRegistry) context.getService(registryReference); + public Object addingService(ServiceReference reference) { + // keyring is now ready + Keyring keyring = (Keyring)context.getService(reference); + // Register Launcher service since FrameworkProvider is waiting for it blockingly. CommandInfoSourceImpl commands = new CommandInfoSourceImpl(bundleService.getConfiguration().getThermostatHome()); - context.registerService(CommandInfoSource.class, commands, null); + cmdInfoReg = context.registerService(CommandInfoSource.class, commands, null); bundleService.setCommandInfoSource(commands); LauncherImpl launcher = new LauncherImpl(context, new CommandContextFactory(context), bundleService); - launcherServiceRegistration = context.registerService(Launcher.class.getName(), launcher, null); + launcherReg = context.registerService(Launcher.class.getName(), launcher, null); + bundleManReg = context.registerService(BundleManager.class, bundleService, null); + return keyring; } @Override - public void dependenciesUnavailable() { - launcherServiceRegistration.unregister(); - context.ungetService(registryReference); + public void modifiedService(ServiceReference reference, Object service) { + // nothing + } + + @Override + public void removedService(ServiceReference reference, Object service) { + // Keyring is gone, remove launcher, et. al. as well + launcherReg.unregister(); + bundleManReg.unregister(); + cmdInfoReg.unregister(); } } @SuppressWarnings("rawtypes") - private ServiceRegistration launcherServiceRegistration; - private MultipleServiceTracker tracker; + private ServiceTracker serviceTracker; + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void start(final BundleContext context) throws Exception { super.start(context); - - tracker = new MultipleServiceTracker(context, new Class[] {OSGiRegistry.class, Keyring.class}, new RegisterLauncherAction(context)); - tracker.open(); + BundleManager bundleService = new BundleManagerImpl(new Configuration()); + ServiceTrackerCustomizer customizer = new RegisterLauncherCustomizer(context, bundleService); + serviceTracker = new ServiceTracker(context, Keyring.class, customizer); + // Track for Keyring service. + serviceTracker.open(); } @Override public void stop(BundleContext context) throws Exception { super.stop(context); - if (tracker != null) { - tracker.close(); + if (serviceTracker != null) { + serviceTracker.close(); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleLoader.java Thu Jan 10 16:16:29 2013 +0100 @@ -0,0 +1,99 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.launcher.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.launch.Framework; + +public class BundleLoader { + + private boolean printOSGiInfo = false; + + BundleLoader() { + this(false); + } + + public BundleLoader(boolean printOSGiInfo) { + setPrintOSGiInfo(printOSGiInfo); + } + + public void setPrintOSGiInfo(boolean printOSGiInfo) { + this.printOSGiInfo = printOSGiInfo; + } + + public List<Bundle> installAndStartBundles(Framework framework, + List<String>bundleLocations) throws BundleException { + List<Bundle> bundles = new ArrayList<>(); + BundleContext ctx = framework.getBundleContext(); + for (String location : bundleLocations) { + Bundle bundle = ctx.installBundle(location); + if (printOSGiInfo) { + System.out.println("BundleLoader: installed bundle: \"" + + location + "\" as id " + bundle.getBundleId()); + } + bundles.add(bundle); + } + startBundles(bundles); + return bundles; + } + + private void startBundles(List<Bundle> bundles) throws BundleException { + for (Bundle bundle : bundles) { + + if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) { + if (printOSGiInfo) { + System.out.println("BundleLoader: bundle \"" + bundle.getBundleId() + "\" is a fragment; not starting it"); + } + continue; + } + + if (printOSGiInfo) { + System.out.println("BundleLoader: starting bundle: \"" + bundle.getBundleId() + "\""); + } + // We don't want for the framework to set the auto-start bit. Thus, passing + // START_TRANSIENT explicitly + bundle.start(Bundle.START_TRANSIENT); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java Thu Jan 10 16:16:29 2013 +0100 @@ -0,0 +1,123 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.launcher.internal; + +import com.redhat.thermostat.common.Configuration; +import com.redhat.thermostat.common.ConfigurationException; +import com.redhat.thermostat.common.cli.CommandInfoNotFoundException; +import com.redhat.thermostat.common.cli.CommandInfoSource; +import com.redhat.thermostat.launcher.BundleManager; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleException; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.launch.Framework; + +public class BundleManagerImpl extends BundleManager { + + private CommandInfoSource commandInfos; + private Map<String, Bundle> loaded; + private Configuration configuration; + private BundleLoader loader; + + BundleManagerImpl(Configuration configuration) throws ConfigurationException, FileNotFoundException, IOException { + initLoadedBundles(); + this.configuration = configuration; + loader = new BundleLoader(configuration.getPrintOSGiInfo()); + } + + private void initLoadedBundles() { + loaded = new HashMap<>(); + Framework framework = getFramework(this.getClass()); + for (Bundle bundle: framework.getBundleContext().getBundles()) { + loaded.put(bundle.getLocation(), bundle); + } + } + + @Override + public void setPrintOSGiInfo(boolean printOSGiInfo) { + configuration.setPrintOSGiInfo(printOSGiInfo); + loader.setPrintOSGiInfo(printOSGiInfo); + } + + @Override + public void setCommandInfoSource(CommandInfoSource source) { + this.commandInfos = source; + } + + @Override + public void addBundlesFor(String commandName) throws BundleException, IOException, CommandInfoNotFoundException { + if (configuration.getPrintOSGiInfo()) { + System.out.println("Loading additional bundles for: " + commandName); + } + List<String> requiredBundles = commandInfos.getCommandInfo(commandName).getDependencyResourceNames(); + List<String> bundlesToLoad = new ArrayList<>(); + if (requiredBundles != null) { + for (String resource : requiredBundles) { + if (!isBundleActive(resource)) { + bundlesToLoad.add(resource); + } + } + } + Framework framework = getFramework(this.getClass()); + List<Bundle> successBundles = loader.installAndStartBundles(framework, bundlesToLoad); + for (Bundle bundle : successBundles) { + loaded.put(bundle.getLocation(), bundle); + } + } + + private boolean isBundleActive(String location) { + Bundle bundle = loaded.get(location); + return (bundle != null) && (bundle.getState() == Bundle.ACTIVE); + } + + private Framework getFramework(Class<?> cls) { + return (Framework) FrameworkUtil.getBundle(cls).getBundleContext().getBundle(0); + } + + @Override + public Configuration getConfiguration() { + return configuration; + } +}
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java Thu Jan 10 21:48:04 2013 +0100 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java Thu Jan 10 16:16:29 2013 +0100 @@ -50,7 +50,6 @@ import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; -import com.redhat.thermostat.bundles.OSGiRegistry; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ActionNotifier; import com.redhat.thermostat.common.ApplicationService; @@ -72,6 +71,7 @@ import com.redhat.thermostat.common.utils.OSGIUtils; import com.redhat.thermostat.launcher.CommonCommandOptions; import com.redhat.thermostat.launcher.Launcher; +import com.redhat.thermostat.launcher.BundleManager; import com.redhat.thermostat.storage.core.ConnectionException; import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.core.StorageException; @@ -89,14 +89,14 @@ private final Semaphore argsBarrier = new Semaphore(0); private BundleContext context; - private OSGiRegistry registry; + private BundleManager registry; private final DbServiceFactory dbServiceFactory; - public LauncherImpl(BundleContext context, CommandContextFactory cmdCtxFactory, OSGiRegistry registry) { + public LauncherImpl(BundleContext context, CommandContextFactory cmdCtxFactory, BundleManager registry) { this(context, cmdCtxFactory, registry, new LoggingInitializer(), new DbServiceFactory()); } - LauncherImpl(BundleContext context, CommandContextFactory cmdCtxFactory, OSGiRegistry registry, + LauncherImpl(BundleContext context, CommandContextFactory cmdCtxFactory, BundleManager registry, LoggingInitializer loggingInitializer, DbServiceFactory dbServiceFactory) { this.context = context; this.cmdCtxFactory = cmdCtxFactory;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/BundleManagerTest.java Thu Jan 10 16:16:29 2013 +0100 @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.launcher; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +import java.util.ArrayList; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.osgi.framework.launch.Framework; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.redhat.thermostat.launcher.BundleManager; +import com.redhat.thermostat.launcher.internal.BundleLoader; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(BundleManager.class) +public class BundleManagerTest { + + @Test + public void testPreLoadBundles() throws Exception { + Framework framework = mock(Framework.class); + ArrayList<String> bundleLocations = new ArrayList<>(); + BundleLoader loader = mock(BundleLoader.class); + whenNew(BundleLoader.class).withParameterTypes(Boolean.TYPE). + withArguments(any()).thenReturn(loader); + + BundleManager.preLoadBundles(framework, bundleLocations, true); + verify(loader).installAndStartBundles(framework, bundleLocations); + } +}
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java Thu Jan 10 21:48:04 2013 +0100 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java Thu Jan 10 16:16:29 2013 +0100 @@ -36,6 +36,9 @@ package com.redhat.thermostat.launcher.internal; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; @@ -46,6 +49,9 @@ import static org.powermock.api.mockito.PowerMockito.verifyNew; import static org.powermock.api.mockito.PowerMockito.whenNew; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Dictionary; import java.util.Hashtable; @@ -55,41 +61,55 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.launch.Framework; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; +import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import com.redhat.thermostat.bundles.OSGiRegistry; import com.redhat.thermostat.common.Configuration; import com.redhat.thermostat.common.MultipleServiceTracker; import com.redhat.thermostat.common.MultipleServiceTracker.Action; import com.redhat.thermostat.common.cli.Command; import com.redhat.thermostat.common.cli.CommandInfo; +import com.redhat.thermostat.common.cli.CommandInfoSource; import com.redhat.thermostat.common.utils.ServiceRegistry; import com.redhat.thermostat.launcher.Launcher; +import com.redhat.thermostat.launcher.BundleManager; +import com.redhat.thermostat.launcher.internal.Activator.RegisterLauncherCustomizer; +import com.redhat.thermostat.test.StubBundleContext; import com.redhat.thermostat.utils.keyring.Keyring; @RunWith(PowerMockRunner.class) -@PrepareForTest({Activator.class}) +@PrepareForTest({Activator.class, Activator.RegisterLauncherCustomizer.class, FrameworkUtil.class}) public class ActivatorTest { private BundleContext context; private MultipleServiceTracker tracker; private ServiceReference registryServiceReference, helpCommandReference; private ServiceRegistration launcherServiceRegistration, helpCommandRegistration; - private OSGiRegistry registryService; + private BundleManager registryService; private Command helpCommand; @Before public void setUp() throws Exception { + Path tempDir = createStubThermostatHome(); + System.setProperty("THERMOSTAT_HOME", tempDir.toString()); + context = mock(BundleContext.class); + setupOsgiRegistryImplMock(); registryServiceReference = mock(ServiceReference.class); launcherServiceRegistration = mock(ServiceRegistration.class); - registryService = mock(OSGiRegistry.class); - when(context.getServiceReference(eq(OSGiRegistry.class))).thenReturn(registryServiceReference); + registryService = mock(BundleManager.class); + when(context.getServiceReference(eq(BundleManager.class))).thenReturn(registryServiceReference); when(context.getService(eq(registryServiceReference))).thenReturn(registryService); when(context.registerService(eq(Launcher.class.getName()), any(), (Dictionary) isNull())). thenReturn(launcherServiceRegistration); @@ -116,32 +136,95 @@ tracker = mock(MultipleServiceTracker.class); whenNew(MultipleServiceTracker.class). withParameterTypes(BundleContext.class, Class[].class, Action.class). - withArguments(eq(context), eq(new Class[] {OSGiRegistry.class, Keyring.class}), + withArguments(eq(context), eq(new Class[] {BundleManager.class, Keyring.class}), isA(Action.class)).thenReturn(tracker); } @Test public void testActivatorLifecycle() throws Exception { + ArgumentCaptor<RegisterLauncherCustomizer> customizerCaptor = ArgumentCaptor.forClass(RegisterLauncherCustomizer.class); + ServiceTracker mockTracker = mock(ServiceTracker.class); + whenNew(ServiceTracker.class).withParameterTypes(BundleContext.class, Class.class, ServiceTrackerCustomizer.class).withArguments(eq(context), + any(Keyring.class), customizerCaptor.capture()).thenReturn(mockTracker); + Activator activator = new Activator(); - activator.start(context); Hashtable<String, Object> props = new Hashtable<>(); props.put(ServiceRegistry.SERVICE_NAME, "help"); verify(context).registerService(eq(Command.class.getName()), isA(HelpCommand.class), eq(props)); - ArgumentCaptor<Action> actionCaptor = ArgumentCaptor.forClass(Action.class); - verifyNew(MultipleServiceTracker.class).withArguments(eq(context), - eq(new Class[] {OSGiRegistry.class, Keyring.class}), - actionCaptor.capture()); - Action action = actionCaptor.getValue(); + verify(mockTracker).open(); + + RegisterLauncherCustomizer customizer = customizerCaptor.getValue(); + assertNotNull(customizer); + activator.stop(context); + verify(mockTracker).close(); + } + + @Test + public void testServiceTrackerCustomizer() throws Exception { + StubBundleContext context = new StubBundleContext(); + ArgumentCaptor<RegisterLauncherCustomizer> customizerCaptor = ArgumentCaptor.forClass(RegisterLauncherCustomizer.class); + ServiceTracker mockTracker = mock(ServiceTracker.class); + whenNew(ServiceTracker.class).withParameterTypes(BundleContext.class, Class.class, ServiceTrackerCustomizer.class).withArguments(eq(context), + any(Keyring.class), customizerCaptor.capture()).thenReturn(mockTracker); + + Activator activator = new Activator(); + context.registerService(Keyring.class, mock(Keyring.class), null); + activator.start(context); + + assertTrue(context.isServiceRegistered(Command.class.getName(), HelpCommand.class)); + + RegisterLauncherCustomizer customizer = customizerCaptor.getValue(); + assertNotNull(customizer); + Keyring keyringService = mock(Keyring.class); + context.registerService(Keyring.class, keyringService, null); + ServiceReference ref = context.getServiceReference(Keyring.class); + customizer.addingService(ref); + + assertTrue(context.isServiceRegistered(CommandInfoSource.class.getName(), mock(CommandInfoSourceImpl.class).getClass())); + assertTrue(context.isServiceRegistered(BundleManager.class.getName(), BundleManagerImpl.class)); + assertTrue(context.isServiceRegistered(Launcher.class.getName(), LauncherImpl.class)); - action.dependenciesAvailable(isA(Map.class)); - verify(context).registerService(eq(Launcher.class.getName()), isA(Launcher.class), (Dictionary) isNull()); + customizer.removedService(null, null); + + assertFalse(context.isServiceRegistered(CommandInfoSource.class.getName(), CommandInfoSourceImpl.class)); + assertFalse(context.isServiceRegistered(BundleManager.class.getName(), BundleManagerImpl.class)); + assertFalse(context.isServiceRegistered(Launcher.class.getName(), LauncherImpl.class)); + } + + private Path createStubThermostatHome() throws Exception { + Path tempDir = Files.createTempDirectory("test"); + tempDir.toFile().deleteOnExit(); + System.setProperty("THERMOSTAT_HOME", tempDir.toString()); + + File tempEtc = new File(tempDir.toFile(), "etc"); + tempEtc.mkdirs(); + tempEtc.deleteOnExit(); + + File tempProps = new File(tempEtc, "osgi-export.properties"); + tempProps.createNewFile(); + tempProps.deleteOnExit(); - activator.stop(context); - // osgi will take care of unregistration on bundle stop - // verify(launcherServiceRegistration).unregister(); - verify(tracker).close(); + File tempBundleProps = new File(tempEtc, "bundles.properties"); + tempBundleProps.createNewFile(); + tempBundleProps.deleteOnExit(); + + File tempLibs = new File(tempDir.toFile(), "libs"); + tempLibs.mkdirs(); + tempLibs.deleteOnExit(); + return tempDir; + } + + private void setupOsgiRegistryImplMock() { + PowerMockito.mockStatic(FrameworkUtil.class); + Bundle mockBundle = mock(Bundle.class); + when(FrameworkUtil.getBundle(BundleManagerImpl.class)).thenReturn(mockBundle); + when(mockBundle.getBundleContext()).thenReturn(context); + Bundle mockFramework = mock(Framework.class); + when(context.getBundle(0)).thenReturn(mockFramework); + when(mockFramework.getBundleContext()).thenReturn(context); + when(context.getBundles()).thenReturn(new Bundle[0]); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleLoaderTest.java Thu Jan 10 16:16:29 2013 +0100 @@ -0,0 +1,103 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.launcher.internal; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import org.junit.Test; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.launch.Framework; + +import com.redhat.thermostat.launcher.internal.BundleLoader; +import com.redhat.thermostat.test.Bug; + +public class BundleLoaderTest { + + @Test + public void verifyBundlesAreInstalledAndStarted() throws BundleException { + final String BUNDLE_LOCATION = "bundle-location-1"; + + Bundle bundle = mock(Bundle.class); + when(bundle.getHeaders()).thenReturn(new Hashtable<String, String>()); + BundleContext bundleContext = mock(BundleContext.class); + when(bundleContext.installBundle(BUNDLE_LOCATION)).thenReturn(bundle); + Framework framework = mock(Framework.class); + when(framework.getBundleContext()).thenReturn(bundleContext); + List<String> bundleLocations = Arrays.asList(BUNDLE_LOCATION); + + BundleLoader loader = new BundleLoader(); + loader.installAndStartBundles(framework, bundleLocations); + + verify(bundle).start(Bundle.START_TRANSIENT); + } + + @Bug(id="1227", + summary="Make sure launcher does not start fragments", + url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1227") + @Test + public void verifyFragmentsAreInstalledButNotStarted() throws BundleException { + final String BUNDLE_LOCATION = "bundle-location-1"; + + Bundle bundle = mock(Bundle.class); + Dictionary<String, String> bundleHeaders = new Hashtable<>(); + bundleHeaders.put(Constants.FRAGMENT_HOST, "foo-bar"); + when(bundle.getHeaders()).thenReturn(bundleHeaders); + + BundleContext bundleContext = mock(BundleContext.class); + when(bundleContext.installBundle(BUNDLE_LOCATION)).thenReturn(bundle); + Framework framework = mock(Framework.class); + when(framework.getBundleContext()).thenReturn(bundleContext); + List<String> bundleLocations = Arrays.asList(BUNDLE_LOCATION); + + BundleLoader loader = new BundleLoader(); + loader.installAndStartBundles(framework, bundleLocations); + + verify(bundle, times(0)).start(Bundle.START_TRANSIENT); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java Thu Jan 10 16:16:29 2013 +0100 @@ -0,0 +1,157 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.launcher.internal; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.launch.Framework; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import com.redhat.thermostat.common.Configuration; +import com.redhat.thermostat.common.cli.CommandInfo; +import com.redhat.thermostat.common.cli.CommandInfoSource; +import com.redhat.thermostat.launcher.internal.BundleLoader; +import com.redhat.thermostat.launcher.internal.BundleManagerImpl; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({BundleManagerImpl.class, FrameworkUtil.class}) +public class BundleManagerImplTest { + + private static final String cmdName = "one"; + + private static final String jar1Name = "/one.jar"; + private static final String jar2Name = "/two.jar"; + private static final String jar3Name = "/three.jar"; + + private Bundle b1, b2, b3; + private List<String> bundleLocs; + + private BundleLoader loader; + private Configuration conf; + + @Before + public void setUp() throws Exception { + conf = mock(Configuration.class); + when(conf.getThermostatHome()).thenReturn("no_matter"); + bundleLocs = Arrays.asList(jar1Name, jar2Name, jar3Name); + b1 = mock(Bundle.class); + when(b1.getLocation()).thenReturn(jar1Name); + when(b1.getState()).thenReturn(Bundle.ACTIVE); + b2 = mock(Bundle.class); + when(b2.getLocation()).thenReturn(jar2Name); + when(b2.getState()).thenReturn(Bundle.ACTIVE); + b3 = mock(Bundle.class); + when(b3.getLocation()).thenReturn(jar3Name); + when(b3.getState()).thenReturn(Bundle.ACTIVE); + List<Bundle> installed = Arrays.asList(b1, b2, b3); + + loader = mock(BundleLoader.class); + when(loader.installAndStartBundles(any(Framework.class), eq(bundleLocs))). + thenReturn(installed); + whenNew(BundleLoader.class).withParameterTypes(Boolean.TYPE). + withArguments(any()).thenReturn(loader); + } + + @Test + public void testLoadBundlesFor() throws Exception { + verifyBundlesLoaded(new Bundle[] {}, bundleLocs); + } + + @Test + public void verifyAlreadyLoadedBundlesNotReloaded() throws Exception { + verifyBundlesLoaded(new Bundle[] {b1, b2}, Arrays.asList(jar3Name)); + } + + private void verifyBundlesLoaded(Bundle[] preloaded, List<String> locationsNeeded) throws Exception { + Bundle theBundle = b2; + BundleContext theContext = mock(BundleContext.class); + when(theContext.getBundles()).thenReturn(preloaded); + Framework theFramework = mock(Framework.class); + when(theFramework.getBundleContext()).thenReturn(theContext); + when(theContext.getBundle(0)).thenReturn(theFramework); + when(theBundle.getBundleContext()).thenReturn(theContext); + mockStatic(FrameworkUtil.class); + when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); + + BundleManagerImpl registry = new BundleManagerImpl(conf); + CommandInfoSource infos = mock(CommandInfoSource.class); + CommandInfo info = mock(CommandInfo.class); + when (info.getDependencyResourceNames()).thenReturn(bundleLocs); + when (infos.getCommandInfo(cmdName)).thenReturn(info); + registry.setCommandInfoSource(infos); + registry.addBundlesFor(cmdName); + verify(loader).installAndStartBundles(any(Framework.class), eq(locationsNeeded)); + } + + @Test + public void verifySetOSGiVerbosityByReflection() throws Exception { + + // All this fluff is just so constructor doesn't NPE. + Bundle theBundle = b2; + BundleContext theContext = mock(BundleContext.class); + when(theContext.getBundles()).thenReturn(new Bundle[]{}); + Framework theFramework = mock(Framework.class); + when(theFramework.getBundleContext()).thenReturn(theContext); + when(theContext.getBundle(0)).thenReturn(theFramework); + when(theBundle.getBundleContext()).thenReturn(theContext); + mockStatic(FrameworkUtil.class); + when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); + + Object registry = new BundleManagerImpl(conf); + Class clazz = registry.getClass(); + Method m = clazz.getMethod("setPrintOSGiInfo", Boolean.TYPE); + m.invoke(registry, true); // If this fails, then API has changed in ways that break FrameworkProvider. + } + +}
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/LauncherTest.java Thu Jan 10 21:48:04 2013 +0100 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/LauncherTest.java Thu Jan 10 16:16:29 2013 +0100 @@ -72,7 +72,6 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import com.redhat.thermostat.bundles.OSGiRegistry; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ActionNotifier; import com.redhat.thermostat.common.ApplicationInfo; @@ -93,6 +92,7 @@ import com.redhat.thermostat.common.tools.ApplicationState; import com.redhat.thermostat.common.tools.BasicCommand; import com.redhat.thermostat.common.utils.OSGIUtils; +import com.redhat.thermostat.launcher.BundleManager; import com.redhat.thermostat.launcher.internal.LauncherImpl.LoggingInitializer; import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.test.StubBundleContext; @@ -144,7 +144,7 @@ private StubBundleContext bundleContext; private Bundle sysBundle; private TestTimerFactory timerFactory; - private OSGiRegistry registry; + private BundleManager registry; private LoggingInitializer loggingInitializer; private DbServiceFactory dbServiceFactory; private CommandInfoSource infos; @@ -211,7 +211,7 @@ ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(new HelpCommand(), cmd1, cmd2, cmd3, basicCmd)); - registry = mock(OSGiRegistry.class); + registry = mock(BundleManager.class); infos = mock(CommandInfoSource.class); when(infos.getCommandInfo(name1)).thenReturn(info1);
--- a/main/pom.xml Thu Jan 10 21:48:04 2013 +0100 +++ b/main/pom.xml Thu Jan 10 16:16:29 2013 +0100 @@ -84,11 +84,6 @@ </dependency> <dependency> <groupId>com.redhat.thermostat</groupId> - <artifactId>thermostat-bundles</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-launcher</artifactId> <version>${project.version}</version> </dependency>
--- a/main/src/main/java/com/redhat/thermostat/main/Thermostat.java Thu Jan 10 21:48:04 2013 +0100 +++ b/main/src/main/java/com/redhat/thermostat/main/Thermostat.java Thu Jan 10 16:16:29 2013 +0100 @@ -62,6 +62,7 @@ this.context = context; } + @SuppressWarnings({ "rawtypes", "unchecked" }) private void launch() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, FileNotFoundException, IOException, BundleException, InterruptedException {
--- a/main/src/main/java/com/redhat/thermostat/main/impl/FrameworkProvider.java Thu Jan 10 21:48:04 2013 +0100 +++ b/main/src/main/java/com/redhat/thermostat/main/impl/FrameworkProvider.java Thu Jan 10 16:16:29 2013 +0100 @@ -59,10 +59,9 @@ import org.osgi.framework.launch.FrameworkFactory; import org.osgi.util.tracker.ServiceTracker; -import com.redhat.thermostat.bundles.OSGiRegistry; import com.redhat.thermostat.common.Configuration; -import com.redhat.thermostat.common.ConfigurationException; import com.redhat.thermostat.launcher.Launcher; +import com.redhat.thermostat.launcher.BundleManager; public class FrameworkProvider { @@ -217,11 +216,11 @@ locations.add(location); } } - OSGiRegistry.preLoadBundles(framework, locations, printOSGiInfo); + BundleManager.preLoadBundles(framework, locations, printOSGiInfo); } private void setLoaderVerbosity(Framework framework) throws InterruptedException { - Object loader = getService(framework, OSGiRegistry.class.getName()); + Object loader = getService(framework, BundleManager.class.getName()); callVoidReflectedMethod(loader, "setPrintOSGiInfo", printOSGiInfo, Boolean.TYPE); } @@ -232,6 +231,7 @@ private Object getService(Framework framework, String name) throws InterruptedException { Object service = null; + @SuppressWarnings({ "unchecked", "rawtypes" }) ServiceTracker tracker = new ServiceTracker(framework.getBundleContext(), name, null); tracker.open(); service = tracker.waitForService(0);
--- a/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties Thu Jan 10 21:48:04 2013 +0100 +++ b/main/src/main/resources/com/redhat/thermostat/main/impl/bootstrapbundles.properties Thu Jan 10 16:16:29 2013 +0100 @@ -1,7 +1,6 @@ bundles=thermostat-keyring-${project.version}.jar, \ thermostat-storage-core-${project.version}.jar, \ thermostat-common-core-${project.version}.jar, \ - thermostat-bundles-${project.version}.jar, \ thermostat-launcher-${project.version}.jar, \ thermostat-main-${project.version}.jar, \ jline2.jar, \
--- a/main/src/test/java/com/redhat/thermostat/main/ThermostatTest.java Thu Jan 10 21:48:04 2013 +0100 +++ b/main/src/test/java/com/redhat/thermostat/main/ThermostatTest.java Thu Jan 10 16:16:29 2013 +0100 @@ -36,27 +36,36 @@ package com.redhat.thermostat.main; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Hashtable; import org.junit.Before; +import org.junit.Test; import org.junit.runner.RunWith; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.launch.Framework; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import com.redhat.thermostat.bundles.impl.OSGiRegistryImpl; -import com.redhat.thermostat.common.Configuration; +import com.redhat.thermostat.launcher.Launcher; +import com.redhat.thermostat.launcher.BundleManager; +import com.redhat.thermostat.main.impl.FrameworkProvider; @RunWith(PowerMockRunner.class) -@PrepareForTest(value = Thermostat.class) +@PrepareForTest({FrameworkProvider.class}) public class ThermostatTest { private Path tempDir; @@ -65,12 +74,9 @@ private BundleContext mockContext; + @SuppressWarnings("rawtypes") @Before public void setUp() throws Exception { - - final OSGiRegistryImpl osgiRegistry = mock(OSGiRegistryImpl.class); - PowerMockito.whenNew(OSGiRegistryImpl.class).withArguments(any(Configuration.class)).thenReturn(osgiRegistry); - tempDir = Files.createTempDirectory("test"); tempDir.toFile().deleteOnExit(); System.setProperty("THERMOSTAT_HOME", tempDir.toString()); @@ -93,19 +99,40 @@ mockContext = mock(BundleContext.class); - mockFramework = mock(Framework.class); - when(mockFramework.getBundleContext()).thenReturn(mockContext); - - TestFrameworkFactory.setFramework(mockFramework); + Framework framework = mock(Framework.class); + TestFrameworkFactory.setFramework(framework); + when(framework.getBundleContext()).thenReturn(mockContext); + Bundle mockBundle = mock(Bundle.class); + when(mockContext.installBundle(any(String.class))).thenReturn(mockBundle); + when(mockBundle.getHeaders()).thenReturn(new Hashtable<String, String>()); + ServiceTracker registryTracker = mock(ServiceTracker.class); + PowerMockito + .whenNew(ServiceTracker.class) + .withParameterTypes(BundleContext.class, String.class, + ServiceTrackerCustomizer.class) + .withArguments(any(BundleContext.class), + eq(BundleManager.class.getName()), any(ServiceTrackerCustomizer.class)) + .thenReturn(registryTracker); + when(registryTracker.waitForService(0)).thenReturn(mock(BundleManager.class)); + ServiceTracker launcherTracker = mock(ServiceTracker.class); + Launcher launcher = mock(Launcher.class); + PowerMockito + .whenNew(ServiceTracker.class) + .withParameterTypes(BundleContext.class, String.class, + ServiceTrackerCustomizer.class) + .withArguments(any(BundleContext.class), + eq(Launcher.class.getName()), + any(ServiceTrackerCustomizer.class)) + .thenReturn(launcherTracker); + when(launcherTracker.waitForService(0)) + .thenReturn(launcher); } - // TODO These now seem to belong in OSGiRegistryTest - - /* @Test public void testOSGIDirExists() throws Exception { - Path osgiDir = tempDir.resolve("osgi"); + Path osgiDir = tempDir.resolve("osgi-cache"); osgiDir.toFile().mkdirs(); + osgiDir.toFile().deleteOnExit(); assertTrue(osgiDir.toFile().exists()); try { Thermostat.main(new String[0]); @@ -113,20 +140,18 @@ e.printStackTrace(); } assertTrue(osgiDir.toFile().exists()); - }*/ - - /*@Test - public void testFrameworkConfig() throws Exception { - Thermostat.main(new String[0]); - Map<String,String> config = TestFrameworkFactory.getConfig(); - Path osgiDir = tempDir.resolve("osgi"); - assertEquals(osgiDir.toString(), config.get(Constants.FRAMEWORK_STORAGE)); } @Test public void testFrameworkInitAndStart() throws Exception { + Path osgiDir = tempDir.resolve("osgi-cache"); + osgiDir.toFile().mkdirs(); + osgiDir.toFile().deleteOnExit(); + mockFramework = mock(Framework.class); + when(mockFramework.getBundleContext()).thenReturn(mockContext); + TestFrameworkFactory.setFramework(mockFramework); Thermostat.main(new String[0]); verify(mockFramework).init(); verify(mockFramework).start(); - }*/ + } }
--- a/main/src/test/resources/META-INF/services/org.osgi.framework.launch.FrameworkFactory Thu Jan 10 21:48:04 2013 +0100 +++ b/main/src/test/resources/META-INF/services/org.osgi.framework.launch.FrameworkFactory Thu Jan 10 16:16:29 2013 +0100 @@ -34,4 +34,4 @@ # to do so, delete this exception statement from your version. # -com.redhat.thermostat.launcher.TestFrameworkFactory \ No newline at end of file +com.redhat.thermostat.main.TestFrameworkFactory \ No newline at end of file