Mercurial > hg > release > thermostat-1.0
changeset 1307:75fe7ce6dea2
PR1591: Thermostat should have a way to specify "any bundle version"
Reviewed-by: vanaltj
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-November/008670.html
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Thu, 07 Nov 2013 15:27:27 -0500 |
parents | ac26a7ee871d |
children | 41126b42f1e3 |
files | config/src/main/java/com/redhat/thermostat/shared/config/Configuration.java launcher/src/main/java/com/redhat/thermostat/launcher/BundleManager.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleLoader.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java main/src/main/java/com/redhat/thermostat/main/Thermostat.java main/src/main/java/com/redhat/thermostat/main/impl/FrameworkProvider.java |
diffstat | 7 files changed, 189 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/config/src/main/java/com/redhat/thermostat/shared/config/Configuration.java Thu Nov 07 14:55:48 2013 -0500 +++ b/config/src/main/java/com/redhat/thermostat/shared/config/Configuration.java Thu Nov 07 15:27:27 2013 -0500 @@ -89,6 +89,7 @@ private final UserDirectories userDirectories; private boolean printOsgiInfo = false; + private boolean ignoreVersions = false; public Configuration() throws InvalidConfigurationException { // allow this to be specified also as a property, especially for @@ -234,6 +235,14 @@ printOsgiInfo = newValue; } + public void setIgnoreVersions(boolean ignore) { + this.ignoreVersions = ignore; + } + + public boolean getIgnoreVersions() { + return ignoreVersions; + } + private interface UserDirectories { public File getSystemRoot(); @@ -351,4 +360,5 @@ return cacheDir; } } + }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/BundleManager.java Thu Nov 07 14:55:48 2013 -0500 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/BundleManager.java Thu Nov 07 15:27:27 2013 -0500 @@ -58,6 +58,17 @@ public abstract void setPrintOSGiInfo(boolean printOSGiInfo); /** + * Indicates that versions in thermostat-specific config files (including + * thermostat-plugin.xml files) should be ignored and the latest version + * used. + * <p> + * This does not change OSGi's requirements; if OSGi bundles need specific + * versions and the latest version is not within the asked range, things + * will break. + */ + public abstract void setIgnoreVersions(boolean ignore); + + /** * Load and start bundles using the metadata about a bundle. */ public abstract void loadBundlesByName(List<BundleInformation> bundles) throws BundleException, IOException;
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleLoader.java Thu Nov 07 14:55:48 2013 -0500 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleLoader.java Thu Nov 07 15:27:27 2013 -0500 @@ -61,6 +61,16 @@ this.printOSGiInfo = printOSGiInfo; } + /** + * Install and start bundles in one step (solving any interdependencies). + * + * @param framework the {@link Framework} to use for installing and starting + * the bundles. + * @param bundleLocations a {@link List} of {@link String}s where each + * {@code String} is a URL of the bundle to load + * @return a {@link List} of {@link Bundle}s that were started. + * @throws BundleException + */ public List<Bundle> installAndStartBundles(Framework framework, List<String> bundleLocations) throws BundleException { List<Bundle> bundles = new ArrayList<>();
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java Thu Nov 07 14:55:48 2013 -0500 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java Thu Nov 07 15:27:27 2013 -0500 @@ -61,6 +61,7 @@ import org.osgi.framework.BundleException; import org.osgi.framework.Constants; import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.Version; import org.osgi.framework.launch.Framework; import com.redhat.thermostat.common.utils.LoggingUtils; @@ -143,6 +144,14 @@ } } + /** For TESTS only: explicitly specify known bundles */ + void setKnownBundles(Map<BundleInformation,Path> knownData) { + known.clear(); + for (Entry<BundleInformation, Path> entry : knownData.entrySet()) { + known.put(entry.getKey(), entry.getValue()); + } + } + @Override public void setPrintOSGiInfo(boolean printOSGiInfo) { configuration.setPrintOSGiInfo(printOSGiInfo); @@ -150,10 +159,22 @@ } @Override + public void setIgnoreVersions(boolean ignore) { + configuration.setIgnoreVersions(ignore); + } + + @Override public void loadBundlesByName(List<BundleInformation> bundles) throws BundleException, IOException { List<String> paths = new ArrayList<>(); for (BundleInformation info : bundles) { - Path bundlePath = known.get(info); + Path bundlePath = null; + + if (configuration.getIgnoreVersions()) { + bundlePath = findLatestVersion(info.getName()); + } else { + bundlePath = known.get(info); + } + if (bundlePath == null) { logger.warning("no known bundle matching " + info.toString()); continue; @@ -163,6 +184,30 @@ loadBundlesByPath(paths); } + private Path findLatestVersion(String bundleSymbolicName) { + BundleInformation bestBundleInformation = null; + Version bestVersion = null; + + Path bundlePath = null; + + for (Entry<BundleInformation, Path> entry: known.entrySet()) { + if (bundleSymbolicName.equals(entry.getKey().getName())) { + Version version = Version.parseVersion(entry.getKey().getVersion()); + if (bestVersion == null || version.compareTo(bestVersion) > 0) { + bestVersion = version; + bestBundleInformation = entry.getKey(); + } + } + } + if (bestBundleInformation != null) { + bundlePath = known.get(bestBundleInformation); + } + + logger.fine("Best match for " + bundleSymbolicName + " is " + bestBundleInformation); + + return bundlePath; + } + /* package private for testing only */ void loadBundlesByPath(List<String> requiredBundles) throws BundleException, IOException { Framework framework = getFramework(this.getClass());
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java Thu Nov 07 14:55:48 2013 -0500 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java Thu Nov 07 15:27:27 2013 -0500 @@ -40,19 +40,25 @@ import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.whenNew; +import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.After; import org.junit.Before; @@ -65,6 +71,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import com.redhat.thermostat.launcher.BundleInformation; import com.redhat.thermostat.shared.config.Configuration; @RunWith(PowerMockRunner.class) @@ -141,8 +148,9 @@ } }); } + @Test - public void testInstallAndStartBundles() throws Exception { + public void verifyInstallAndStartBundles() throws Exception { Bundle theBundle = b2; when(theContext.getBundles()).thenReturn(new Bundle[] {}); when(theBundle.getBundleContext()).thenReturn(theContext); @@ -157,6 +165,95 @@ } @Test + public void verifyLoadBundleByNameAndVersionWithBundleNotFound() throws Exception { + Bundle theBundle = b2; + when(theContext.getBundles()).thenReturn(new Bundle[] {}); + when(theBundle.getBundleContext()).thenReturn(theContext); + + mockStatic(FrameworkUtil.class); + + when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); + + BundleManagerImpl registry = new BundleManagerImpl(conf); + Map<BundleInformation, Path> bundleToPath = new HashMap<>(); + + registry.setKnownBundles(bundleToPath); + + registry.loadBundlesByName(Arrays.asList(new BundleInformation("foo", "1.0"))); + + verify(loader).installAndStartBundles(theFramework, Arrays.<String>asList()); + } + + @Test + public void verifyLoadBundleByNameAndVersion() throws Exception { + + Bundle theBundle = b2; + when(theContext.getBundles()).thenReturn(new Bundle[] {}); + when(theBundle.getBundleContext()).thenReturn(theContext); + + mockStatic(FrameworkUtil.class); + + when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); + + BundleManagerImpl registry = new BundleManagerImpl(conf); + Map<BundleInformation, Path> bundleToPath = new HashMap<>(); + bundleToPath.put(new BundleInformation("foo", "1.0"), Paths.get(jar1Name)); + registry.setKnownBundles(bundleToPath); + + registry.loadBundlesByName(Arrays.asList(new BundleInformation("foo", "1.0"))); + + verify(loader).installAndStartBundles(theFramework, Arrays.asList(new File(jar1Name).toURI().toURL().toString())); + } + + @Test + public void verifyLoadBundleByNameAndLatestVersion() throws Exception { + + Bundle theBundle = b2; + when(theContext.getBundles()).thenReturn(new Bundle[] {}); + when(theBundle.getBundleContext()).thenReturn(theContext); + + mockStatic(FrameworkUtil.class); + + when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); + + when(conf.getIgnoreVersions()).thenReturn(true); + + BundleManagerImpl registry = new BundleManagerImpl(conf); + Map<BundleInformation, Path> bundleToPath = new HashMap<>(); + bundleToPath.put(new BundleInformation("foo", "1.0"), Paths.get(jar1Name)); + bundleToPath.put(new BundleInformation("foo", "2.0"), Paths.get(jar2Name)); + + registry.setKnownBundles(bundleToPath); + + registry.loadBundlesByName(Arrays.asList(new BundleInformation("foo", "3.0"))); + + verify(loader).installAndStartBundles(theFramework, Arrays.asList(new File(jar2Name).toURI().toURL().toString())); + } + + @Test + public void verifyLoadBundleByNameAndLatestVersionWithoutSupportForLatestVersion() throws Exception { + + Bundle theBundle = b2; + when(theContext.getBundles()).thenReturn(new Bundle[] {}); + when(theBundle.getBundleContext()).thenReturn(theContext); + + mockStatic(FrameworkUtil.class); + + when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle); + + BundleManagerImpl registry = new BundleManagerImpl(conf); + Map<BundleInformation, Path> bundleToPath = new HashMap<>(); + bundleToPath.put(new BundleInformation("foo", "1.0"), Paths.get(jar1Name)); + bundleToPath.put(new BundleInformation("foo", "2.0"), Paths.get(jar2Name)); + + registry.setKnownBundles(bundleToPath); + + registry.loadBundlesByName(Arrays.asList(new BundleInformation("foo", "3.0"))); + + verify(loader).installAndStartBundles(theFramework, new ArrayList<String>()); + } + + @Test public void verifyAlreadyLoadedBundlesNotReloaded() throws Exception { Bundle theBundle = b2; @@ -170,7 +267,7 @@ BundleManagerImpl registry = new BundleManagerImpl(conf); registry.loadBundlesByPath(bundleLocs); - verify(loader).installAndStartBundles(any(Framework.class), eq(Arrays.asList(jar3Name))); + verify(loader).installAndStartBundles(theFramework, Arrays.asList(jar3Name)); } @Test
--- a/main/src/main/java/com/redhat/thermostat/main/Thermostat.java Thu Nov 07 14:55:48 2013 -0500 +++ b/main/src/main/java/com/redhat/thermostat/main/Thermostat.java Thu Nov 07 15:27:27 2013 -0500 @@ -57,10 +57,14 @@ Iterator<String> iter = toProcess.iterator(); while (iter.hasNext()) { String arg = iter.next(); - if (("--print-osgi-info").equals(arg)) { + if ("--print-osgi-info".equals(arg)) { config.setPrintOSGiInfo(true); iter.remove(); } + if ("--ignore-bundle-versions".equals(arg)) { + config.setIgnoreVersions(true); + iter.remove(); + } } FrameworkProvider frameworkProvider = new FrameworkProvider(config);
--- a/main/src/main/java/com/redhat/thermostat/main/impl/FrameworkProvider.java Thu Nov 07 14:55:48 2013 -0500 +++ b/main/src/main/java/com/redhat/thermostat/main/impl/FrameworkProvider.java Thu Nov 07 15:27:27 2013 -0500 @@ -72,12 +72,14 @@ private Configuration configuration; private boolean printOSGiInfo; + private boolean ignoreVersions; // The framework cache location; Must not be shared between apps! private Path osgiCacheStorage; public FrameworkProvider(Configuration config) { this.configuration = config; printOSGiInfo = config.getPrintOSGiInfo(); + ignoreVersions = config.getIgnoreVersions(); } // This is our ticket into OSGi land. Unfortunately, we to use a bit of reflection here. @@ -89,6 +91,7 @@ prepareFramework(framework); loadBootstrapBundles(framework); setLoaderVerbosity(framework); + setIgnoreBundleVersions(framework); runLauncher(framework, args); } catch (InterruptedException | BundleException | IOException e) { throw new RuntimeException("Could not start framework.", e); @@ -227,6 +230,11 @@ callVoidReflectedMethod(loader, "setPrintOSGiInfo", printOSGiInfo); } + private void setIgnoreBundleVersions(Framework framework) throws InterruptedException { + Object loader = getService(framework, BundleManager.class.getName()); + callVoidReflectedMethod(loader, "setIgnoreVersions", ignoreVersions); + } + private void runLauncher(Framework framework, String[] args) throws InterruptedException { Object launcher = getService(framework, Launcher.class.getName()); callVoidReflectedMethod(launcher, "run", args, false);