changeset 1182:cb2842943f60

Use SymblicName and Version in thermostat-plugin.xml Reviewed-by: neugens, jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-July/007583.html
author Omair Majid <omajid@redhat.com>
date Wed, 24 Jul 2013 13:56:13 -0400
parents 468d91f69d67
children 9ec44cd38946
files distribution/docs/thermostat-plugin.xsd distribution/pom.xml host-cpu/distribution/thermostat-plugin.xml host-memory/distribution/thermostat-plugin.xml host-overview/distribution/thermostat-plugin.xml launcher/src/main/java/com/redhat/thermostat/launcher/BundleInformation.java launcher/src/main/java/com/redhat/thermostat/launcher/BundleManager.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/BasicCommandInfo.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/BuiltInCommandInfo.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/main/java/com/redhat/thermostat/launcher/internal/CommandInfo.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSource.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfiguration.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/BasicCommandInfoTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/TestCommandInfo.java numa/distribution/thermostat-plugin.xml pom.xml storage/mongo/pom.xml thread/distribution/thermostat-plugin.xml validate-command/distribution/thermostat-plugin.xml vm-classstat/distribution/thermostat-plugin.xml vm-cpu/distribution/thermostat-plugin.xml vm-gc/distribution/thermostat-plugin.xml vm-heap-analysis/distribution/thermostat-plugin.xml vm-jmx/distribution/thermostat-plugin.xml vm-memory/distribution/thermostat-plugin.xml vm-overview/distribution/thermostat-plugin.xml
diffstat 34 files changed, 667 insertions(+), 426 deletions(-) [+]
line wrap: on
line diff
--- a/distribution/docs/thermostat-plugin.xsd	Fri Jul 19 15:35:58 2013 +0200
+++ b/distribution/docs/thermostat-plugin.xsd	Wed Jul 24 13:56:13 2013 -0400
@@ -7,8 +7,8 @@
 
 <!-- definition of simple elements -->
 <xs:element name="name" type="xs:string"/>
-<xs:element name="bundle" type="xs:string"/>
-<xs:element name="dependency" type="xs:string"/>
+<xs:element name="symbolic-name" type="xs:string"/>
+<xs:element name="version" type="xs:string"/>
 <xs:element name="usage" type="xs:string"/>
 <xs:element name="description" type="xs:string"/>
 <xs:element name="short" type="xs:string"/>
@@ -53,13 +53,6 @@
     <xs:sequence>
       <xs:element ref="name"/>
       <xs:element ref="bundles"/>
-      <xs:element ref="dependencies" minOccurs="0" maxOccurs="1">
-      <xs:annotation>
-        <xs:documentation>
-          Dependencies: depend on other libraries.
-        </xs:documentation>
-      </xs:annotation>
-      </xs:element>
     </xs:sequence>
   </xs:complexType>
 </xs:element>
@@ -75,13 +68,6 @@
       <xs:element ref="options" minOccurs="0" maxOccurs="1"/>
       <xs:element ref="environments"/>
       <xs:element ref="bundles"/>
-      <xs:element ref="dependencies">
-      <xs:annotation>
-        <xs:documentation>
-          Dependencies: depend on other commands.
-        </xs:documentation>
-      </xs:annotation>
-      </xs:element>
     </xs:sequence>
   </xs:complexType>
 </xs:element> 
@@ -169,6 +155,11 @@
 </xs:element>
 
 <xs:element name="bundles">
+  <xs:annotation>
+    <xs:documentation>
+      Specifies OSGi bundles
+    </xs:documentation>
+  </xs:annotation>
   <xs:complexType>
     <xs:sequence>
       <xs:element ref="bundle" minOccurs="1" maxOccurs="unbounded"/>
@@ -176,14 +167,30 @@
   </xs:complexType>
 </xs:element>
 
-
-<xs:element name="dependencies">
+<xs:element name="bundle">
+  <xs:annotation>
+    <xs:documentation>
+      Specifies an OSGi bundle
+    </xs:documentation>
+  </xs:annotation>
   <xs:complexType>
     <xs:sequence>
-      <xs:element ref="dependency" minOccurs="1" maxOccurs="unbounded"/>
+      <xs:element ref="symbolic-name">
+        <xs:annotation>
+          <xs:documentation>
+            The 'Bundle-SymbolicName' of the OSGi bundle
+          </xs:documentation>
+        </xs:annotation>
+      </xs:element>
+      <xs:element ref="version">
+        <xs:annotation>
+          <xs:documentation>
+            The 'Bundle-Version' of the OSGi bundle
+          </xs:documentation>
+        </xs:annotation>
+      </xs:element>
     </xs:sequence>
   </xs:complexType>
 </xs:element>
 
-
 </xs:schema>
--- a/distribution/pom.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/distribution/pom.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -261,7 +261,7 @@
                 <symlink link="${project.build.directory}/libs/commons-collections.jar"
                          resource="${project.build.directory}/libs/commons-collections-3.2.1.jar" />
                 <symlink link="${project.build.directory}/libs/commons-logging.jar"
-                         resource="${project.build.directory}/libs/com.springsource.org.apache.commons.logging-1.1.1.jar" />
+                         resource="${project.build.directory}/libs/commons-logging-1.1.3.jar" />
                 <symlink link="${project.build.directory}/libs/lucene.jar"
                          resource="${project.build.directory}/libs/org.apache.servicemix.bundles.lucene-3.6.0_1.jar" />
                 <symlink link="${project.build.directory}/libs/gson.jar"
--- a/host-cpu/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/host-cpu/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,23 +43,23 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-host-cpu-common-${project.version}.jar</bundle>
-        <bundle>thermostat-host-cpu-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-host-cpu-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.cpu.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.cpu.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.cpu.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-host-cpu-common-${project.version}.jar</bundle>
-        <bundle>thermostat-host-cpu-agent-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.cpu.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.cpu.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-host-cpu-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.cpu.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/host-memory/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/host-memory/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,23 +43,23 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-host-memory-common-${project.version}.jar</bundle>
-        <bundle>thermostat-host-memory-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-host-memory-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.memory.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.memory.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.memory.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-host-memory-common-${project.version}.jar</bundle>
-        <bundle>thermostat-host-memory-agent-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.memory.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.memory.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-host-memory-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.memory.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/host-overview/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/host-overview/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,8 +43,8 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-host-overview-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-host-overview-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.overview.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.host.overview.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/BundleInformation.java	Wed Jul 24 13:56:13 2013 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012, 2013 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.util.Objects;
+
+/**
+ * Represents basic meta-data about a bundle, including the
+ * {@code Bundle-SymbolicName} and {@code Bundle-Version}.
+ */
+public class BundleInformation {
+    private final String name;
+    private final String version;
+
+    /**
+     * @param name the {@code Bundle-SymbolicName} of the bundle
+     * @param version the {@code Bundle-Version} of the bundle
+     */
+    public BundleInformation(final String name, final String version) {
+        this.name = name;
+        this.version = version;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    @Override
+    public String toString() {
+        return "Bundle[" + name + "=" + version + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, version);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        BundleInformation other = (BundleInformation) obj;
+        return Objects.equals(name, other.getName()) && Objects.equals(version, other.getVersion());
+    }
+
+}
\ No newline at end of file
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/BundleManager.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/BundleManager.java	Wed Jul 24 13:56:13 2013 -0400
@@ -48,13 +48,26 @@
 
 /**
  * A Service that provides features to load bundles for given command names.
+ * <p>
+ * It can install bundles in to the current runtime and start them. It can find
+ * bundles by file paths or by bundle meta-data.
  */
 @Service
 public abstract class BundleManager {
 
     public abstract void setPrintOSGiInfo(boolean printOSGiInfo);
 
-    public abstract void addBundles(List<String> dependencies) throws BundleException, IOException;
+    /**
+     * Load and start bundles using the metadata about a bundle.
+     */
+    public abstract void loadBundlesByName(List<BundleInformation> bundles) throws BundleException, IOException;
+
+    /**
+     * Load and start bundles using file locations
+     *
+     * @param uriPaths a list of URI strings that represent on-disk locations of bundles
+     */
+    public abstract void loadBundlesByPath(List<String> uriPaths) throws BundleException, IOException;
 
     public static void preLoadBundles(Framework framework, List<String> bundleLocations,
             boolean printOSGiInfo) throws BundleException {
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BasicCommandInfo.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BasicCommandInfo.java	Wed Jul 24 13:56:13 2013 -0400
@@ -36,11 +36,14 @@
 
 package com.redhat.thermostat.launcher.internal;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.commons.cli.Options;
 
+import com.redhat.thermostat.launcher.BundleInformation;
+
 public class BasicCommandInfo implements CommandInfo {
 
     private final String name;
@@ -49,6 +52,7 @@
     private final Options options;
     private final Set<Environment> environments;
     private final List<String> resources;
+    private final List<BundleInformation> bundles;
 
     public BasicCommandInfo(String name, String description, String usage, Options options, Set<Environment> environments, List<String> resources) {
         this.name = name;
@@ -57,6 +61,17 @@
         this.options = options;
         this.environments = environments;
         this.resources = resources;
+        this.bundles = Collections.emptyList();
+    }
+
+    public BasicCommandInfo(String name, String description, String usage, Options options, Set<Environment> environments, List<String> resources, List<BundleInformation> bundles) {
+        this.name = name;
+        this.description = description;
+        this.usage = usage;
+        this.options = options;
+        this.environments = environments;
+        this.resources = resources;
+        this.bundles = bundles;
     }
 
     @Override
@@ -90,7 +105,12 @@
     }
 
     @Override
+    public List<BundleInformation> getBundles() {
+        return bundles;
+    }
+
+    @Override
     public String toString() {
-        return String.format("%s (description='%s', dependencies='%s')", name, description, resources.toString());
+        return String.format("%s (description='%s', dependencies='%s', bundles='%s')", name, description, resources.toString(), bundles.toString());
     }
 }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BuiltInCommandInfo.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BuiltInCommandInfo.java	Wed Jul 24 13:56:13 2013 -0400
@@ -40,6 +40,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map.Entry;
@@ -52,6 +53,7 @@
 import org.apache.commons.cli.Options;
 
 import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.shared.config.InvalidConfigurationException;
 
 public class BuiltInCommandInfo implements CommandInfo {
@@ -381,5 +383,10 @@
     public List<String> getDependencyResourceNames() {
         return dependencies;
     }
+
+    @Override
+    public List<BundleInformation> getBundles() {
+        return Collections.emptyList();
+    }
 }
 
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleLoader.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleLoader.java	Wed Jul 24 13:56:13 2013 -0400
@@ -62,7 +62,7 @@
     }
 
     public List<Bundle> installAndStartBundles(Framework framework,
-            List<String>bundleLocations) throws BundleException {
+            List<String> bundleLocations) throws BundleException {
         List<Bundle> bundles = new ArrayList<>();
         BundleContext ctx = framework.getBundleContext();
         for (String location : bundleLocations) {
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java	Wed Jul 24 13:56:13 2013 -0400
@@ -38,38 +38,93 @@
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
+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.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.naming.ConfigurationException;
 
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.launch.Framework;
 
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.launcher.BundleManager;
 import com.redhat.thermostat.shared.config.Configuration;
 
 public class BundleManagerImpl extends BundleManager {
 
-    private Map<String, Bundle> loaded;
+    private static final Logger logger = LoggingUtils.getLogger(BundleManagerImpl.class);
+
+    // Bundle Name and version -> path
+    private final Map<BundleInformation, Path> known;
     private Configuration configuration;
     private BundleLoader loader;
 
     BundleManagerImpl(Configuration configuration) throws ConfigurationException, FileNotFoundException, IOException {
-        initLoadedBundles();
+        known = new HashMap<>();
+
         this.configuration = configuration;
         loader = new BundleLoader(configuration.getPrintOSGiInfo());
+
+        scanForBundles();
     }
 
-    private void initLoadedBundles() {
-        loaded = new HashMap<>();
-        Framework framework = getFramework(this.getClass());
-        for (Bundle bundle: framework.getBundleContext().getBundles()) {
-            loaded.put(bundle.getLocation(), bundle);
+    private void scanForBundles() {
+        long t1 = System.nanoTime();
+
+        try {
+            for (String root : new String[] { configuration.getLibRoot(), configuration.getPluginRoot() }) {
+                Files.walkFileTree(Paths.get(root), new SimpleFileVisitor<Path>() {
+                    @Override
+                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                        if (file.toFile().getName().endsWith(".jar")) {
+                            try (JarFile jf = new JarFile(file.toFile())) {
+                                Manifest mf = jf.getManifest();
+                                String name = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+                                String version = mf.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
+                                if (name == null || version == null) {
+                                    logger.config("file " + file.toString() + " is missing osgi metadata; wont be usable for dependencies");
+                                } else {
+                                    known.put(new BundleInformation(name, version), file);
+                                }
+                            } catch (IOException e) {
+                                logger.severe("Error in reading " + file);
+                                // continue with other files, even if one file is broken
+                            }
+                        }
+                        return FileVisitResult.CONTINUE;
+                    }
+                });
+            }
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "Error scanning bundles for metadata", e);
+        }
+
+        long t2 = System.nanoTime();
+        if (configuration.getPrintOSGiInfo()) {
+            logger.fine("Found: " + known.size() + " bundles");
+            logger.fine("Took " + (t2 -t1) + "ns");
+
+            for (Entry<BundleInformation, Path> bundles : known.entrySet()) {
+                logger.finest(bundles.getKey().toString() + " is at " + bundles.getValue().toString());
+            }
         }
     }
 
@@ -80,24 +135,37 @@
     }
 
     @Override
-    public void addBundles(List<String> requiredBundles) throws BundleException, IOException {
+    public void loadBundlesByName(List<BundleInformation> bundles) throws BundleException, IOException {
+        List<String> paths = new ArrayList<>();
+        for (BundleInformation info : bundles) {
+            Path bundlePath = known.get(info);
+            if (bundlePath == null) {
+                logger.warning("no known bundle matching " + info.toString());
+                continue;
+            }
+            paths.add(bundlePath.toFile().toURI().toString());
+        }
+        loadBundlesByPath(paths);
+    }
+
+    @Override
+    public void loadBundlesByPath(List<String> requiredBundles) throws BundleException, IOException {
+        Framework framework = getFramework(this.getClass());
+        BundleContext context = framework.getBundleContext();
+
         List<String> bundlesToLoad = new ArrayList<>();
         if (requiredBundles != null) {
             for (String resource : requiredBundles) {
-                if (!isBundleActive(resource)) {
+                if (!isBundleActive(context, 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);
-        }
+        loader.installAndStartBundles(framework, bundlesToLoad);
     }
 
-    private boolean isBundleActive(String location) {
-        Bundle bundle = loaded.get(location);
+    private boolean isBundleActive(BundleContext context, String location) {
+        Bundle bundle = context.getBundle(location);
         return (bundle != null) && (bundle.getState() == Bundle.ACTIVE);
     }
 
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CommandInfo.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CommandInfo.java	Wed Jul 24 13:56:13 2013 -0400
@@ -41,6 +41,8 @@
 
 import org.apache.commons.cli.Options;
 
+import com.redhat.thermostat.launcher.BundleInformation;
+
 public interface CommandInfo {
 
     /**
@@ -71,8 +73,10 @@
      */
     public Options getOptions();
 
+    List<BundleInformation> getBundles();
+
     /** Returns a list of jar that this command depends on */
-    public List<String> getDependencyResourceNames();
+    List<String> getDependencyResourceNames();
 
 }
 
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSource.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSource.java	Wed Jul 24 13:56:13 2013 -0400
@@ -46,6 +46,8 @@
 
 import org.apache.commons.cli.Options;
 
+import com.redhat.thermostat.launcher.BundleInformation;
+
 
 
 /**
@@ -135,8 +137,12 @@
         List<String> resources = new ArrayList<>();
         resources.addAll(info1.getDependencyResourceNames());
         resources.addAll(info2.getDependencyResourceNames());
+        List<BundleInformation> bundles = new ArrayList<>();
+        bundles.addAll(info1.getBundles());
+        bundles.addAll(info2.getBundles());
 
-        return new BasicCommandInfo(name, description, usage, options, environment, resources);
+
+        return new BasicCommandInfo(name, description, usage, options, environment, resources, bundles);
     }
 
     private <T> T selectBest(T first, T second) {
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java	Wed Jul 24 13:56:13 2013 -0400
@@ -245,7 +245,8 @@
         }
 
         try {
-            registry.addBundles(cmdInfo.getDependencyResourceNames());
+            registry.loadBundlesByPath(cmdInfo.getDependencyResourceNames());
+            registry.loadBundlesByName(cmdInfo.getBundles());
         } catch (BundleException | IOException e) {
             // If this happens we definitely need to do something about it, and the
             // trace will be immeasurably helpful in figuring out what is wrong.
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java	Wed Jul 24 13:56:13 2013 -0400
@@ -40,6 +40,7 @@
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -50,6 +51,7 @@
 import java.util.logging.Logger;
 
 import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.CommandExtensions;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.NewCommand;
 import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException;
@@ -73,7 +75,7 @@
     private final UsageStringBuilder usageBuilder;
 
     private Map<String, BasicCommandInfo> allNewCommands = new HashMap<>();
-    private Map<String, List<String>> additionalBundlesForExistingCommands = new HashMap<>();
+    private Map<String, List<BundleInformation>> additionalBundlesForExistingCommands = new HashMap<>();
 
     public PluginCommandInfoSource(String internalJarRoot, String pluginRootDir) {
         this(new File(internalJarRoot), new File(pluginRootDir), new PluginConfigurationParser(), new UsageStringBuilder());
@@ -111,19 +113,16 @@
 
         for (CommandExtensions extension : pluginConfig.getExtendedCommands()) {
             String commandName = extension.getCommandName();
-            List<String> pluginBundles = extension.getPluginBundles();
-            List<String> dependencyBundles = extension.getDepenedencyBundles();
-            logger.config("plugin at " + pluginDir + " contributes " +
-                    pluginBundles.size() + " bundles to comamnd '" + commandName + "'");
+            List<BundleInformation> bundles = extension.getBundles();
+            logger.config("plugin at " + pluginDir + " needs " +
+                    bundles.size() + " bundles for comamnd '" + commandName + "'");
 
-            List<String> bundlePaths = additionalBundlesForExistingCommands.get(commandName);
+            List<BundleInformation> bundlePaths = additionalBundlesForExistingCommands.get(commandName);
             if (bundlePaths == null) {
                 bundlePaths = new LinkedList<>();
             }
 
-            addIfValidPath(bundlePaths, pluginDir, pluginBundles);
-
-            addIfValidPath(bundlePaths, coreJarRoot, dependencyBundles);
+            bundlePaths.addAll(bundles);
 
             additionalBundlesForExistingCommands.put(commandName, bundlePaths);
         }
@@ -136,12 +135,6 @@
                 throw new IllegalStateException("multiple plugins are providing the command " + commandName);
             }
 
-            List<String> bundlePaths = new LinkedList<>();
-
-            addIfValidPath(bundlePaths, pluginDir, command.getPluginBundles());
-
-            addIfValidPath(bundlePaths, coreJarRoot, command.getDepenedencyBundles());
-
             String usage = command.getUsage();
             if (usage == null) {
                 usage = usageBuilder.getUsage(commandName, command.getOptions(), command.getPositionalArguments().toArray(new String[0]));
@@ -151,38 +144,29 @@
                     usage,
                     command.getOptions(),
                     command.getEnvironments(),
-                    bundlePaths);
+                    Collections.<String>emptyList(),
+                    command.getBundles());
 
             allNewCommands.put(commandName, info);
         }
 
     }
 
-    private void addIfValidPath(List<String> result, File parentDir, List<String> pathsRelativeToParent) {
-        for (String bundle : pathsRelativeToParent) {
-            File bundleFile = new File(parentDir, bundle);
-            if (bundleFile.isFile()) {
-                result.add(bundleFile.toURI().toString());
-            } else {
-                logger.warning("File " + bundleFile.toString() + " not found. Removing it from list of bundles to load.");
-            }
-        }
-    }
-
     private void combineCommands() {
-        Iterator<Entry<String, List<String>>> iter = additionalBundlesForExistingCommands.entrySet().iterator();
+        Iterator<Entry<String, List<BundleInformation>>> iter = additionalBundlesForExistingCommands.entrySet().iterator();
         while (iter.hasNext()) {
-            Map.Entry<String, List<String>> entry = iter.next();
+            Map.Entry<String, List<BundleInformation>> entry = iter.next();
             if (allNewCommands.containsKey(entry.getKey())) {
                 BasicCommandInfo old = allNewCommands.get(entry.getKey());
-                List<String> updatedResources = new ArrayList<>();
-                updatedResources.addAll(old.getDependencyResourceNames());
+                List<BundleInformation> updatedResources = new ArrayList<>();
+                updatedResources.addAll(old.getBundles());
                 updatedResources.addAll(entry.getValue());
                 BasicCommandInfo updated = new BasicCommandInfo(old.getName(),
                         old.getDescription(),
                         old.getUsage(),
                         old.getOptions(),
                         old.getEnvironments(),
+                        Collections.<String>emptyList(),
                         updatedResources);
                 allNewCommands.put(entry.getKey(), updated);
                 iter.remove();
@@ -195,9 +179,9 @@
         if (allNewCommands.containsKey(name)) {
             return allNewCommands.get(name);
         }
-        List<String> bundles = additionalBundlesForExistingCommands.get(name);
+        List<BundleInformation> bundles = additionalBundlesForExistingCommands.get(name);
         if (bundles != null) {
-            return new BasicCommandInfo(name, null, null, null, null, bundles);
+            return new BasicCommandInfo(name, null, null, null, null, Collections.<String>emptyList(), bundles);
         }
         throw new CommandInfoNotFoundException(name);
     }
@@ -206,8 +190,8 @@
     public Collection<CommandInfo> getCommandInfos() {
         List<CommandInfo> result = new ArrayList<>();
         result.addAll(allNewCommands.values());
-        for (Entry<String, List<String>> entry : additionalBundlesForExistingCommands.entrySet()) {
-            result.add(new BasicCommandInfo(entry.getKey(), null, null, null, null, entry.getValue()));
+        for (Entry<String, List<BundleInformation>> entry : additionalBundlesForExistingCommands.entrySet()) {
+            result.add(new BasicCommandInfo(entry.getKey(), null, null, null, null, Collections.<String>emptyList(), entry.getValue()));
         }
         return result;
     }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfiguration.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfiguration.java	Wed Jul 24 13:56:13 2013 -0400
@@ -36,12 +36,15 @@
 
 package com.redhat.thermostat.launcher.internal;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.commons.cli.Options;
 
+import com.redhat.thermostat.launcher.BundleInformation;
+
 
 public class PluginConfiguration {
 
@@ -64,25 +67,24 @@
     public static class CommandExtensions {
 
         private final String commandName;
-        private final List<String> additionalResources;
-        private final List<String> coreDeps;
+        private final List<BundleInformation> toLoad;
 
-        public CommandExtensions(String name, List<String> additionalResources, List<String> coreDeps) {
+        public CommandExtensions(String name, List<BundleInformation> toLoad) {
             this.commandName = name;
-            this.additionalResources = additionalResources;
-            this.coreDeps = coreDeps;
+            this.toLoad = toLoad;
         }
 
         public String getCommandName() {
             return commandName;
         }
 
-        public List<String> getPluginBundles() {
-            return Collections.unmodifiableList(additionalResources);
+        public List<BundleInformation> getBundles() {
+            return toLoad;
         }
 
-        public List<String> getDepenedencyBundles() {
-            return coreDeps;
+        @Override
+        public String toString() {
+            return "extends " + commandName + " using " + toLoad.toString();
         }
     }
 
@@ -94,21 +96,19 @@
         private final List<String> positionalArguments;
         private final Options options;
         private final Set<Environment> environment;
-        private final List<String> additionalResources;
-        private final List<String> coreDeps;
+        private final List<BundleInformation> bundles;
 
         public NewCommand(String name, String usage, String description,
                 List<String> positionalArguments, Options options,
                 Set<Environment> environment,
-                List<String> additionalResources, List<String> coreDeps) {
+                List<BundleInformation> bundles) {
             this.commandName = name;
             this.usage = usage;
             this.description = description;
             this.positionalArguments = positionalArguments;
             this.options = options;
             this.environment = environment;
-            this.additionalResources = additionalResources;
-            this.coreDeps = coreDeps;
+            this.bundles = bundles;
         }
 
         public String getCommandName() {
@@ -143,15 +143,10 @@
             return Collections.unmodifiableSet(environment);
         }
 
-        public List<String> getPluginBundles() {
-            return Collections.unmodifiableList(additionalResources);
+        public List<BundleInformation> getBundles() {
+            return Collections.unmodifiableList(bundles);
         }
 
-        public List<String> getDepenedencyBundles() {
-            return Collections.unmodifiableList(coreDeps);
-        }
-
-
     }
 
 }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java	Wed Jul 24 13:56:13 2013 -0400
@@ -65,6 +65,7 @@
 import org.xml.sax.SAXParseException;
 
 import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.CommandExtensions;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.NewCommand;
 import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException;
@@ -141,11 +142,11 @@
         &lt;environment&gt;shell&lt;/environment&gt;
       &lt;/environments&gt;
       &lt;bundles&gt;
-        &lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-        &lt;bundle&gt;thermostat-platform-swing-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.core&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.swing&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
       &lt;/bundles&gt;
       &lt;dependencies&gt;
-        &lt;dependency&gt;thermostat-client-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
+        &lt;bundle&gt;&lt;name&gt;client.core&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
       &lt;/dependencies&gt;
     &lt;/command&gt;
     &lt;command&gt;
@@ -174,11 +175,11 @@
         &lt;environment&gt;shell&lt;/environment&gt;
       &lt;/environments&gt;
       &lt;bundles&gt;
-        &lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-        &lt;bundle&gt;thermostat-platform-controllers-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.common&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.controllers&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
       &lt;/bundles&gt;
       &lt;dependencies&gt;
-        &lt;dependency&gt;thermostat-common-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
+        &lt;bundle&gt;&lt;name&gt;common.core&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
       &lt;/dependencies&gt;
     &lt;/command&gt;
   &lt;/commands&gt;
@@ -186,15 +187,15 @@
     &lt;extension&gt;
       &lt;name&gt;platform3&lt;/name&gt;
       &lt;bundles&gt;
-        &lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-        &lt;bundle&gt;thermostat-platform-controllers-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-        &lt;bundle&gt;thermostat-platform-command-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-        &lt;bundle&gt;thermostat-platform-common-export-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-        &lt;bundle&gt;thermostat-platform-swing-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.common&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.controllers&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.command&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.common-export&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;platform.swing&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
       &lt;/bundles&gt;
       &lt;dependencies&gt;
-        &lt;dependency&gt;thermostat-common-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
-        &lt;dependency&gt;thermostat-client-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
+        &lt;bundle&gt;&lt;name&gt;common.core&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
+        &lt;bundle&gt;&lt;name&gt;client.core&lt;/name&gt;&lt;version&gt;0.6.0&lt;/version&gt;&lt;/bundle&gt;
       &lt;/dependencies&gt;
     &lt;/extension&gt;
   &lt;/extensions&gt;
@@ -294,8 +295,7 @@
 
     private CommandExtensions parseAdditionsToExistingCommand(String pluginName, Node commandNode) {
         String name = null;
-        List<String> bundles = new ArrayList<>();
-        List<String> dependencies = new ArrayList<>();
+        List<BundleInformation> bundles = new ArrayList<>();
 
         NodeList nodes = commandNode.getChildNodes();
         for (int i = 0; i < nodes.getLength(); i++) {
@@ -304,8 +304,6 @@
                 name = node.getTextContent().trim();
             } else if (node.getNodeName().equals("bundles")) {
                 bundles.addAll(parseBundles(pluginName, name, node));
-            } else if (node.getNodeName().equals("dependencies")) {
-                dependencies.addAll(parseDependencies(pluginName, name, node));
             }
         }
 
@@ -317,7 +315,7 @@
             logger.warning("plugin " + pluginName + " provides extensions without specifying the command");
             return null;
         }
-        return new CommandExtensions(name, bundles, dependencies);
+        return new CommandExtensions(name, bundles);
     }
 
     private NewCommand parseNewCommand(String pluginName, Node commandNode) {
@@ -327,8 +325,7 @@
         List<String> arguments = new ArrayList<>();
         Options options = new Options();
         Set<Environment> availableInEnvironments = EnumSet.noneOf(Environment.class);
-        List<String> bundles = new ArrayList<>();
-        List<String> dependencies = new ArrayList<>();
+        List<BundleInformation> bundles = new ArrayList<>();
 
         NodeList nodes = commandNode.getChildNodes();
         for (int i = 0; i < nodes.getLength(); i++) {
@@ -347,33 +344,61 @@
                 availableInEnvironments = parseEnvironment(pluginName, name, node);
             } else if (node.getNodeName().equals("bundles")) {
                 bundles.addAll(parseBundles(pluginName, name, node));
-            } else if (node.getNodeName().equals("dependencies")) {
-                dependencies.addAll(parseDependencies(pluginName, name, node));
             }
         }
 
         if (bundles.isEmpty()) {
             logger.warning("plugin " + pluginName  + " provides a new command " + name + " but supplies no bundles");
         }
-        if (dependencies.isEmpty()) {
-            logger.warning("plugin " + pluginName  + " provides a new command " + name + " but lists no dependencies on thermostat");
-        }
 
         if (name == null || description == null || availableInEnvironments.isEmpty()) {
             logger.warning("plugin " + pluginName + " provides an incomplete new command: " +
                     "name='" + name + "', description='" + description + "', options='" + options + "'");
             return null;
         } else {
-            return new NewCommand(name, usage, description, arguments, options, availableInEnvironments, bundles, dependencies);
+            return new NewCommand(name, usage, description, arguments, options, availableInEnvironments, bundles);
         }
     }
 
-    private Collection<String> parseBundles(String pluginName, String commandName, Node bundlesNode) {
-        return parseNodeAsList(pluginName, commandName, bundlesNode, "bundle");
+    private List<BundleInformation> parseBundles(String pluginName, String commandName, Node bundlesNode) {
+        List<BundleInformation> result = new ArrayList<>();
+        NodeList nodes = bundlesNode.getChildNodes();
+        for (int i = 0; i < nodes.getLength(); i++) {
+            Node node = nodes.item(i);
+            if (node.getNodeName().equals("bundle")) {
+                BundleInformation bundleInfo = parseBundle(pluginName, commandName, node);
+                if (bundleInfo != null) {
+                    result.add(bundleInfo);
+                }
+            }
+        }
+        return result;
     }
 
-    private Collection<String> parseDependencies(String pluginName, String commandName, Node dependenciesNode) {
-        return parseNodeAsList(pluginName, commandName, dependenciesNode, "dependency");
+    private BundleInformation parseBundle(String pluginName, String commandName, Node bundleNode) {
+        String name = null;
+        String version = null;
+        NodeList nodes = bundleNode.getChildNodes();
+        for (int i = 0; i < nodes.getLength(); i++) {
+            Node node = nodes.item(i);
+            if (node.getNodeName().equals("symbolic-name")) {
+                name = node.getTextContent().trim();
+            } else if (node.getNodeName().equals("version")) {
+                version = node.getTextContent().trim();
+                // FIXME hack: convert maven-style qualifiers to osgi-style qualifiers.
+                // thermostat uses ${project.version}, which is the maven version, in the
+                // plugin.xml files. This converts that maven -SNAPSHOT into OSGi .SNAPSHOT
+                if (version.endsWith("-SNAPSHOT")) {
+                    version = version.replace("-SNAPSHOT", ".SNAPSHOT");
+                }
+            }
+        }
+        if (name == null || version == null) {
+            logger.warning("plugin " + pluginName  + " has an empty bundles element for command " + name);
+            return null;
+        }
+
+        return new BundleInformation(name, version);
     }
 
     private List<String> parseArguments(String pluginName, String commandName, Node argumentsNode) {
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BasicCommandInfoTest.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BasicCommandInfoTest.java	Wed Jul 24 13:56:13 2013 -0400
@@ -46,6 +46,8 @@
 import org.apache.commons.cli.Options;
 import org.junit.Test;
 
+import com.redhat.thermostat.launcher.BundleInformation;
+
 
 public class BasicCommandInfoTest {
 
@@ -57,6 +59,7 @@
         final Options OPTIONS = new Options();
         final Set<Environment> ENVIRONMENT = EnumSet.noneOf(Environment.class);
         final List<String> RESOURCES = Collections.emptyList();
+        final List<BundleInformation> BUNDLES = Collections.emptyList();
 
         BasicCommandInfo info = new BasicCommandInfo(NAME, DESCRIPTION, USAGE, OPTIONS, ENVIRONMENT, RESOURCES);
 
@@ -66,6 +69,7 @@
         assertEquals(OPTIONS, info.getOptions());
         assertEquals(RESOURCES, info.getDependencyResourceNames());
 
-        assertEquals(String.format("%s (description='%s', dependencies='%s')", NAME, DESCRIPTION, RESOURCES.toString()), info.toString());
+        assertEquals(String.format("%s (description='%s', dependencies='%s', bundles='%s')", NAME, DESCRIPTION, RESOURCES.toString(), BUNDLES.toString()),
+                info.toString());
     }
 }
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java	Wed Jul 24 13:56:13 2013 -0400
@@ -38,16 +38,25 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 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.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Arrays;
 import java.util.List;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -58,6 +67,7 @@
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException;
 import com.redhat.thermostat.shared.config.Configuration;
 
 @RunWith(PowerMockRunner.class)
@@ -73,13 +83,31 @@
     private Bundle b1, b2, b3;
     private List<String> bundleLocs;
 
+    private Framework theFramework;
+    private BundleContext theContext;
+
     private BundleLoader loader;
     private Configuration conf;
+
+    private Path testRoot;
     
     @Before
     public void setUp() throws Exception {
+        testRoot = Files.createTempDirectory("thermostat");
+        Path pluginRootDir = testRoot.resolve("plugins");
+        Files.createDirectory(pluginRootDir);
+        Path jarRootDir = testRoot.resolve("libs");
+        Files.createDirectories(jarRootDir);
+
         conf = mock(Configuration.class);
-        when(conf.getThermostatHome()).thenReturn("no_matter");
+        when(conf.getLibRoot()).thenReturn(jarRootDir.toFile().getPath());
+        when(conf.getPluginRoot()).thenReturn(pluginRootDir.toFile().getPath());
+
+        theContext = mock(BundleContext.class);
+        theFramework = mock(Framework.class);
+        when(theFramework.getBundleContext()).thenReturn(theContext);
+        when(theContext.getBundle(0)).thenReturn(theFramework);
+
         bundleLocs = Arrays.asList(jar1Name, jar2Name, jar3Name);
         b1 = mock(Bundle.class);
         when(b1.getLocation()).thenReturn(jar1Name);
@@ -99,30 +127,55 @@
                 withArguments(any()).thenReturn(loader);
     }
 
+    @After
+    public void tearDown() throws IOException {
+        Files.walkFileTree(testRoot, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                Files.delete(file);
+                return FileVisitResult.CONTINUE;
+            }
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                if (exc == null) {
+                    Files.delete(dir);
+                    return FileVisitResult.CONTINUE;
+                } else {
+                    throw exc;
+                }
+            }
+        });
+    }
     @Test
-    public void testLoadBundlesFor() throws Exception {
-        verifyBundlesLoaded(new Bundle[] {}, bundleLocs);
+    public void testInstallAndStartBundles() 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);
+        registry.loadBundlesByPath(bundleLocs);
+        verify(loader).installAndStartBundles(any(Framework.class), eq(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(theContext.getBundles()).thenReturn(new Bundle[] {b1, b2});
+        when(theContext.getBundle(jar1Name)).thenReturn(b1);
+        when(theContext.getBundle(jar2Name)).thenReturn(b2);
+
         when(theBundle.getBundleContext()).thenReturn(theContext);
         mockStatic(FrameworkUtil.class);
         when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(theBundle);
 
         BundleManagerImpl registry = new BundleManagerImpl(conf);
-        registry.addBundles(bundleLocs);
-        verify(loader).installAndStartBundles(any(Framework.class), eq(locationsNeeded));
+        registry.loadBundlesByPath(bundleLocs);
+        verify(loader).installAndStartBundles(any(Framework.class), eq(Arrays.asList(jar3Name)));
     }
 
     @Test
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java	Wed Jul 24 13:56:13 2013 -0400
@@ -63,6 +63,7 @@
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
+import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.CommandExtensions;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.NewCommand;
 import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException;
@@ -148,21 +149,14 @@
 
     @Test
     public void verifyCommandInfoObjectsToExtendExistingCommandsAreCreated() throws IOException {
-        final String DEPENDENCY_BUNDLE = "dependency-bundle";
-        final String PLUGIN_BUNDLE = "plugin-bundle";
+        BundleInformation bundleInfo = new BundleInformation("plugin-bundle", "0.1");
 
         Path pluginDir = pluginRootDir.resolve("plugin1");
         Files.createDirectory(pluginDir);
-        Path pluginJar = pluginDir.resolve(PLUGIN_BUNDLE);
-        Files.createFile(pluginJar);
-
-        Path dependencyJar = jarRootDir.resolve(DEPENDENCY_BUNDLE);
-        Files.createFile(dependencyJar);
 
         CommandExtensions extensions = mock(CommandExtensions.class);
         when(extensions.getCommandName()).thenReturn("command-name");
-        when(extensions.getPluginBundles()).thenReturn(Arrays.asList(PLUGIN_BUNDLE));
-        when(extensions.getDepenedencyBundles()).thenReturn(Arrays.asList(DEPENDENCY_BUNDLE));
+        when(extensions.getBundles()).thenReturn(Arrays.asList(bundleInfo));
 
         when(parserResult.getExtendedCommands()).thenReturn(Arrays.asList(extensions));
 
@@ -171,11 +165,7 @@
         CommandInfo info = source.getCommandInfo("command-name");
         assertEquals("command-name", info.getName());
 
-        String expectedDep1Name = pluginJar.toFile().toURI().toString();
-        String expectedDep2Name = dependencyJar.toFile().toURI().toString();
-
-        assertTrue(info.getDependencyResourceNames().contains(expectedDep1Name));
-        assertTrue(info.getDependencyResourceNames().contains(expectedDep2Name));
+        assertTrue(info.getBundles().contains(bundleInfo));
     }
 
     @Test
@@ -185,16 +175,10 @@
         final String USAGE = "usage";
         final Options OPTIONS = new Options();
         final Set<Environment> ENVIRONMENTS = EnumSet.of(Environment.SHELL);
-        final String PLUGIN_BUNDLE = "plugin-bundle.jar";
-        final String DEPENDENCY_BUNDLE = "dependency-bundle.jar";
+        BundleInformation bundleInfo = new BundleInformation("plugin-bundle", "0.1");
 
         Path pluginDir = pluginRootDir.resolve("plugin1");
         Files.createDirectory(pluginDir);
-        Path pluginJar = pluginDir.resolve(PLUGIN_BUNDLE);
-        Files.createFile(pluginJar);
-
-        Path dependencyJar = jarRootDir.resolve(DEPENDENCY_BUNDLE);
-        Files.createFile(dependencyJar);
 
         NewCommand cmd = mock(NewCommand.class);
         when(cmd.getCommandName()).thenReturn(NAME);
@@ -202,8 +186,7 @@
         when(usageBuilder.getUsage(NAME, OPTIONS)).thenReturn(USAGE);
         when(cmd.getOptions()).thenReturn(OPTIONS);
         when(cmd.getEnvironments()).thenReturn(ENVIRONMENTS);
-        when(cmd.getPluginBundles()).thenReturn(Arrays.asList(PLUGIN_BUNDLE));
-        when(cmd.getDepenedencyBundles()).thenReturn(Arrays.asList(DEPENDENCY_BUNDLE));
+        when(cmd.getBundles()).thenReturn(Arrays.asList(bundleInfo));
 
         when(parserResult.getNewCommands()).thenReturn(Arrays.asList(cmd));
 
@@ -216,12 +199,8 @@
         assertEquals(USAGE, result.getUsage());
         assertEquals(OPTIONS, result.getOptions());
 
-        String expectedDep1Name = pluginJar.toFile().toURI().toString();
-        String expectedDep2Name = dependencyJar.toFile().toURI().toString();
-
-        List<String> deps = result.getDependencyResourceNames();
-        assertEquals(2, deps.size());
-        assertTrue(deps.contains(expectedDep1Name));
-        assertTrue(deps.contains(expectedDep2Name));
+        List<BundleInformation> deps = result.getBundles();
+        assertEquals(1, deps.size());
+        assertTrue(deps.contains(bundleInfo));
     }
 }
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java	Wed Jul 24 13:56:13 2013 -0400
@@ -54,6 +54,7 @@
 import org.apache.commons.cli.Options;
 import org.junit.Test;
 
+import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.CommandExtensions;
 import com.redhat.thermostat.launcher.internal.PluginConfiguration.NewCommand;
 import com.redhat.thermostat.shared.locale.Translate;
@@ -93,9 +94,9 @@
                 "    <extension>\n" +
                 "      <name>test</name>\n" +
                 "      <bundles>\n" +
-                "        <bundle>foo</bundle>\n" +
-                "        <bundle>bar</bundle>\n" +
-                "        <bundle>baz</bundle>\n" +
+                "        <bundle><symbolic-name>foo</symbolic-name><version>1.0</version></bundle>\n" +
+                "        <bundle><symbolic-name>bar</symbolic-name><version>1.0</version></bundle>\n" +
+                "        <bundle><symbolic-name>baz</symbolic-name><version>1.0</version></bundle>\n" +
                 "      </bundles>\n" +
                 "      <dependencies>\n" +
                 "        <dependency>thermostat-foo</dependency>\n" +
@@ -114,9 +115,10 @@
 
         CommandExtensions first = extensions.get(0);
         assertEquals("test", first.getCommandName());
-        assertEquals(Arrays.asList("foo", "bar", "baz"), first.getPluginBundles());
-        assertEquals(Arrays.asList("thermostat-foo"), first.getDepenedencyBundles());
-    }
+        BundleInformation[] expectedBundles = new BundleInformation[] {
+                new BundleInformation("foo", "1.0"), new BundleInformation("bar", "1.0"), new BundleInformation("baz", "1.0"),
+        };
+        assertEquals(Arrays.asList(expectedBundles), first.getBundles());    }
     
     @Test
     public void testConfigurationThatAddsNewCommand() throws UnsupportedEncodingException {
@@ -133,9 +135,9 @@
                 "        <environment>cli</environment>" +
                 "      </environments>" +
                 "      <bundles>\n" +
-                "        <bundle>foo</bundle>\n" +
-                "        <bundle>bar</bundle>\n" +
-                "        <bundle>baz</bundle>\n" +
+                "        <bundle><symbolic-name>foo</symbolic-name><version>1.0</version></bundle>\n" +
+                "        <bundle><symbolic-name>bar</symbolic-name><version>1.0</version></bundle>\n" +
+                "        <bundle><symbolic-name>baz</symbolic-name><version>1.0</version></bundle>\n" +
                 "      </bundles>\n" +
                 "      <dependencies>\n" +
                 "        <dependency>thermostat-foo</dependency>\n" +
@@ -161,8 +163,10 @@
         assertTrue(opts.getRequiredOptions().isEmpty());
         assertTrue(newCommand.getEnvironments().contains(Environment.SHELL));
         assertTrue(newCommand.getEnvironments().contains(Environment.CLI));
-        assertEquals(Arrays.asList("foo", "bar", "baz"), newCommand.getPluginBundles());
-        assertEquals(Arrays.asList("thermostat-foo"), newCommand.getDepenedencyBundles());
+        BundleInformation[] expectedBundles = new BundleInformation[] {
+                new BundleInformation("foo", "1.0"), new BundleInformation("bar", "1.0"), new BundleInformation("baz", "1.0"),
+        };
+        assertEquals(Arrays.asList(expectedBundles), newCommand.getBundles());
     }
 
     @Test
@@ -175,9 +179,9 @@
                 "    <extension>\n" +
                 "      <name>\ntest   \n</name>\n" +
                 "      <bundles>\n" +
-                "        <bundle>\n \t  \nfoo\t \n \n</bundle>\n" +
-                "        <bundle>\tbar  baz\n</bundle>\n" +
-                "        <bundle>buzz</bundle>\n" +
+                "        <bundle><symbolic-name>\n \t  \nfoo\t \n</symbolic-name><version>ignore</version>\n</bundle>\n" +
+                "        <bundle><symbolic-name>\tbar  baz\n</symbolic-name><version>ignore</version></bundle>\n" +
+                "        <bundle><symbolic-name>buzz</symbolic-name><version>ignore</version></bundle>\n" +
                 "      </bundles>\n" +
                 "      <dependencies>\n\t\n\t \t\t\n" +
                 "        <dependency>\t\t\t  thermostat-foo\n\t\t\n</dependency>\n" +
@@ -196,8 +200,10 @@
 
         CommandExtensions first = extensions.get(0);
         assertEquals("test", first.getCommandName());
-        assertEquals(Arrays.asList("foo", "bar  baz", "buzz"), first.getPluginBundles());
-        assertEquals(Arrays.asList("thermostat-foo"), first.getDepenedencyBundles());
+        BundleInformation[] expectedBundles = new BundleInformation[] {
+                new BundleInformation("foo", "ignore"), new BundleInformation("bar  baz", "ignore"), new BundleInformation("buzz", "ignore"),
+        };
+        assertEquals(Arrays.asList(expectedBundles), first.getBundles());
     }
 
     @Test
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/TestCommandInfo.java	Fri Jul 19 15:35:58 2013 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/TestCommandInfo.java	Wed Jul 24 13:56:13 2013 -0400
@@ -43,6 +43,8 @@
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 
+import com.redhat.thermostat.launcher.BundleInformation;
+
 public class TestCommandInfo implements CommandInfo {
 
     private String name;
@@ -104,4 +106,8 @@
         return Collections.emptyList();
     }
 
+    @Override
+    public List<BundleInformation> getBundles() {
+        return Collections.emptyList();
+    }
 }
--- a/numa/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/numa/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,23 +43,23 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-numa-common-${project.version}.jar</bundle>
-        <bundle>thermostat-numa-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-numa-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.numa.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.numa.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.numa.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-numa-common-${project.version}.jar</bundle>
-        <bundle>thermostat-numa-agent-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.numa.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.numa.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-numa-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.numa.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/pom.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/pom.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -81,8 +81,9 @@
     <commons-cli.version>1.2</commons-cli.version>
     <commons-io.version>2.4</commons-io.version>
     <commons-collections.version>3.2.1</commons-collections.version>
-    <commons-logging.version>1.1.1</commons-logging.version>
+    <commons-logging.version>1.1.3</commons-logging.version>
     <commons-codec.version>1.7</commons-codec.version>
+    <commons-codec.osgi-version>1.7.0</commons-codec.osgi-version>
 
     <jline.version>2.9</jline.version>
     <lucene.version>3.6.0_1</lucene.version>
@@ -110,16 +111,6 @@
         <enabled>false</enabled>
       </snapshots>
     </repository>
-    <repository>
-      <id>com.springsource.repository.bundles.release</id>
-      <name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</name>
-      <url>http://repository.springsource.com/maven/bundles/release</url>
-    </repository>
-    <repository>
-      <id>com.springsource.repository.bundles.external</id>
-      <name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
-      <url>http://repository.springsource.com/maven/bundles/external</url>
-    </repository> 
   </repositories>
 
   <modules>
@@ -340,9 +331,8 @@
         <version>${commons-collections.version}</version>
       </dependency>
       <dependency>
-        <!-- comes from spring repo -->
-        <groupId>org.apache.commons</groupId>
-        <artifactId>com.springsource.org.apache.commons.logging</artifactId>
+        <groupId>commons-logging</groupId>
+        <artifactId>commons-logging</artifactId>
         <version>${commons-logging.version}</version>
       </dependency>
       <dependency>
--- a/storage/mongo/pom.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/storage/mongo/pom.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -99,8 +99,8 @@
       <artifactId>commons-collections</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>com.springsource.org.apache.commons.logging</artifactId>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
     </dependency>
     <dependency>
       <groupId>org.powermock</groupId>
--- a/thread/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/thread/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,24 +43,24 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-thread-collector-${project.version}.jar</bundle>
-        <bundle>thermostat-thread-client-swing-${project.version}.jar</bundle>
-        <bundle>thermostat-thread-client-controllers-${project.version}.jar</bundle>
-        <bundle>thermostat-thread-client-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.thread.collector</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.thread.client.swing</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.thread.client.controller</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.thread.client.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-thread-collector-${project.version}.jar</bundle>
-        <bundle>thermostat-thread-harvester-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.thread.collector</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.thread.harvester</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-thread-collector-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.thread.collector</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/validate-command/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/validate-command/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -51,13 +51,11 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-validate-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.validate.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.shared.config</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.plugin.validator</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-core-${project.version}.jar</dependency>
-        <dependency>thermostat-shared-config-${project.version}.jar</dependency>
-        <dependency>thermostat-plugin-validator-${project.version}.jar</dependency>
-      </dependencies>
     </command>
   </commands>
-</plugin>
\ No newline at end of file
+</plugin>
--- a/vm-classstat/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/vm-classstat/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,23 +43,23 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-vm-classstat-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-classstat-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-classstat-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.classstat.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.classstat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.classstat.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-vm-classstat-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-classstat-agent-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.classstat.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.classstat.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-vm-classstat-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.classstat.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/vm-cpu/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/vm-cpu/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,30 +43,30 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-vm-cpu-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-cpu-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-cpu-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-vm-cpu-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-cpu-agent-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-vm-cpu-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>vm-stat</name>
       <bundles>
-        <bundle>thermostat-vm-cpu-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-cpu-client-cli-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.cpu.client.cli</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/vm-gc/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/vm-gc/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,28 +43,28 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-vm-gc-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-gc-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-gc-client-swing-${project.version}.jar</bundle>
-        <bundle>thermostat-gc-remote-collector-common-${project.version}.jar</bundle>
-        <bundle>thermostat-gc-remote-collector-client-common-${project.version}.jar</bundle>
-        <bundle>thermostat-gc-remote-collector-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.gc.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.gc.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.gc.client.swing</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.gc.remote.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.gc.remote.client.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.gc.remote.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-vm-gc-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-gc-agent-${project.version}.jar</bundle>
-        <bundle>thermostat-gc-remote-collector-common-${project.version}.jar</bundle>
-        <bundle>thermostat-gc-remote-collector-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.gc.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.gc.agent</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.gc.remote.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.gc.remote.command</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-vm-gc-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.gc.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/vm-heap-analysis/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/vm-heap-analysis/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -70,27 +70,25 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.mongodb</symbolic-name><version>${mongo-driver.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-core-${project.version}.jar</dependency>
-        <dependency>thermostat-client-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-cli-${project.version}.jar</dependency>
-        <dependency>thermostat-storage-mongodb-${project.version}.jar</dependency>
-        <dependency>thermostat-web-common-${project.version}.jar</dependency>
-        <dependency>thermostat-web-client-${project.version}.jar</dependency>
-        <dependency>mongo.jar</dependency>
-        <dependency>commons-beanutils.jar</dependency>
-        <dependency>commons-codec.jar</dependency>
-        <dependency>commons-collections.jar</dependency>
-        <dependency>commons-logging.jar</dependency>
-        <dependency>httpcomponents-core.jar</dependency>
-        <dependency>httpcomponents-client.jar</dependency>
-        <dependency>gson.jar</dependency>
-        <dependency>netty.jar</dependency>
-      </dependencies>
     </command>
     <command>
       <name>find-objects</name>
@@ -125,27 +123,25 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.mongodb</symbolic-name><version>${mongo-driver.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-core-${project.version}.jar</dependency>
-        <dependency>thermostat-client-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-cli-${project.version}.jar</dependency>
-        <dependency>thermostat-storage-mongodb-${project.version}.jar</dependency>
-        <dependency>thermostat-web-common-${project.version}.jar</dependency>
-        <dependency>thermostat-web-client-${project.version}.jar</dependency>
-        <dependency>mongo.jar</dependency>
-        <dependency>commons-beanutils.jar</dependency>
-        <dependency>commons-codec.jar</dependency>
-        <dependency>commons-collections.jar</dependency>
-        <dependency>commons-logging.jar</dependency>
-        <dependency>httpcomponents-core.jar</dependency>
-        <dependency>httpcomponents-client.jar</dependency>
-        <dependency>gson.jar</dependency>
-        <dependency>netty.jar</dependency>
-      </dependencies>
     </command>
     <command>
       <name>find-root</name>
@@ -183,27 +179,25 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.mongodb</symbolic-name><version>${mongo-driver.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-core-${project.version}.jar</dependency>
-        <dependency>thermostat-client-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-cli-${project.version}.jar</dependency>
-        <dependency>thermostat-storage-mongodb-${project.version}.jar</dependency>
-        <dependency>thermostat-web-common-${project.version}.jar</dependency>
-        <dependency>thermostat-web-client-${project.version}.jar</dependency>
-        <dependency>mongo.jar</dependency>
-        <dependency>commons-beanutils.jar</dependency>
-        <dependency>commons-codec.jar</dependency>
-        <dependency>commons-collections.jar</dependency>
-        <dependency>commons-logging.jar</dependency>
-        <dependency>httpcomponents-core.jar</dependency>
-        <dependency>httpcomponents-client.jar</dependency>
-        <dependency>gson.jar</dependency>
-        <dependency>netty.jar</dependency>
-      </dependencies>
     </command>
     <command>
       <name>list-heap-dumps</name>
@@ -235,27 +229,25 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.mongodb</symbolic-name><version>${mongo-driver.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-core-${project.version}.jar</dependency>
-        <dependency>thermostat-client-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-cli-${project.version}.jar</dependency>
-        <dependency>thermostat-storage-mongodb-${project.version}.jar</dependency>
-        <dependency>thermostat-web-common-${project.version}.jar</dependency>
-        <dependency>thermostat-web-client-${project.version}.jar</dependency>
-        <dependency>mongo.jar</dependency>
-        <dependency>commons-beanutils.jar</dependency>
-        <dependency>commons-codec.jar</dependency>
-        <dependency>commons-collections.jar</dependency>
-        <dependency>commons-logging.jar</dependency>
-        <dependency>httpcomponents-core.jar</dependency>
-        <dependency>httpcomponents-client.jar</dependency>
-        <dependency>gson.jar</dependency>
-        <dependency>netty.jar</dependency>
-      </dependencies>
     </command>
     <command>
       <name>object-info</name>
@@ -287,27 +279,25 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.mongodb</symbolic-name><version>${mongo-driver.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-core-${project.version}.jar</dependency>
-        <dependency>thermostat-client-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-cli-${project.version}.jar</dependency>
-        <dependency>thermostat-storage-mongodb-${project.version}.jar</dependency>
-        <dependency>thermostat-web-common-${project.version}.jar</dependency>
-        <dependency>thermostat-web-client-${project.version}.jar</dependency>
-        <dependency>mongo.jar</dependency>
-        <dependency>commons-beanutils.jar</dependency>
-        <dependency>commons-codec.jar</dependency>
-        <dependency>commons-collections.jar</dependency>
-        <dependency>commons-logging.jar</dependency>
-        <dependency>httpcomponents-core.jar</dependency>
-        <dependency>httpcomponents-client.jar</dependency>
-        <dependency>gson.jar</dependency>
-        <dependency>netty.jar</dependency>
-      </dependencies>
     </command>
     <command>
       <name>save-heap-dump-to-file</name>
@@ -339,27 +329,25 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.mongodb</symbolic-name><version>${mongo-driver.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-core-${project.version}.jar</dependency>
-        <dependency>thermostat-client-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-cli-${project.version}.jar</dependency>
-        <dependency>thermostat-storage-mongodb-${project.version}.jar</dependency>
-        <dependency>thermostat-web-common-${project.version}.jar</dependency>
-        <dependency>thermostat-web-client-${project.version}.jar</dependency>
-        <dependency>mongo.jar</dependency>
-        <dependency>commons-beanutils.jar</dependency>
-        <dependency>commons-codec.jar</dependency>
-        <dependency>commons-collections.jar</dependency>
-        <dependency>commons-logging.jar</dependency>
-        <dependency>httpcomponents-core.jar</dependency>
-        <dependency>httpcomponents-client.jar</dependency>
-        <dependency>gson.jar</dependency>
-        <dependency>netty.jar</dependency>
-      </dependencies>
     </command>
     <command>
       <name>show-heap-histogram</name>
@@ -384,51 +372,50 @@
         <environment>shell</environment>
       </environments>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.mongodb</symbolic-name><version>${mongo-driver.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
       </bundles>
-      <dependencies>
-        <dependency>thermostat-common-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-core-${project.version}.jar</dependency>
-        <dependency>thermostat-client-command-${project.version}.jar</dependency>
-        <dependency>thermostat-client-cli-${project.version}.jar</dependency>
-        <dependency>thermostat-storage-mongodb-${project.version}.jar</dependency>
-        <dependency>thermostat-web-common-${project.version}.jar</dependency>
-        <dependency>thermostat-web-client-${project.version}.jar</dependency>
-        <dependency>mongo.jar</dependency>
-        <dependency>commons-beanutils.jar</dependency>
-        <dependency>commons-codec.jar</dependency>
-        <dependency>commons-collections.jar</dependency>
-        <dependency>commons-logging.jar</dependency>
-        <dependency>httpcomponents-core.jar</dependency>
-        <dependency>httpcomponents-client.jar</dependency>
-        <dependency>gson.jar</dependency>
-        <dependency>netty.jar</dependency>
-      </dependencies>
     </command>
   </commands>
   <extensions>
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-command-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-heap-analysis-agent-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-vm-heap-analysis-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.heap.analysis.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/vm-jmx/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/vm-jmx/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,16 +43,16 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-vm-jmx-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-jmx-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-jmx-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.jmx.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.jmx.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.jmx.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-vm-jmx-agent-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-jmx-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.jmx.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.jmx.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/vm-memory/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/vm-memory/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,30 +43,30 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-vm-memory-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-memory-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-memory-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>agent</name>
       <bundles>
-        <bundle>thermostat-vm-memory-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-memory-agent-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.agent</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <!-- Requires all storage entity classes to be loaded -->
     <extension>
       <name>webservice</name>
       <bundles>
-        <bundle>thermostat-vm-memory-common-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.common</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
     <extension>
       <name>vm-stat</name>
       <bundles>
-        <bundle>thermostat-vm-memory-common-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-memory-client-cli-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.memory.client.cli</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>
--- a/vm-overview/distribution/thermostat-plugin.xml	Fri Jul 19 15:35:58 2013 +0200
+++ b/vm-overview/distribution/thermostat-plugin.xml	Wed Jul 24 13:56:13 2013 -0400
@@ -43,8 +43,8 @@
     <extension>
       <name>gui</name>
       <bundles>
-        <bundle>thermostat-vm-overview-client-core-${project.version}.jar</bundle>
-        <bundle>thermostat-vm-overview-client-swing-${project.version}.jar</bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.overview.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.overview.client.swing</symbolic-name><version>${project.version}</version></bundle>
       </bundles>
     </extension>
   </extensions>