You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2015/03/15 01:45:46 UTC

karaf-cellar git commit: [KARAF-3615] Cellar keeps bundleId Synchronizers don't broadcast events anymore

Repository: karaf-cellar
Updated Branches:
  refs/heads/cellar-2.3.x 85703afc4 -> 01651af84


[KARAF-3615] Cellar keeps bundleId
Synchronizers don't broadcast events anymore


Project: http://git-wip-us.apache.org/repos/asf/karaf-cellar/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf-cellar/commit/01651af8
Tree: http://git-wip-us.apache.org/repos/asf/karaf-cellar/tree/01651af8
Diff: http://git-wip-us.apache.org/repos/asf/karaf-cellar/diff/01651af8

Branch: refs/heads/cellar-2.3.x
Commit: 01651af84594c63034f56cd19450cb4eac9b28c2
Parents: 85703af
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Sun Mar 15 01:44:54 2015 +0100
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Sun Mar 15 01:44:54 2015 +0100

----------------------------------------------------------------------
 .../apache/karaf/cellar/bundle/BundleState.java | 27 ++++++++++++
 .../karaf/cellar/bundle/BundleSynchronizer.java | 28 +++----------
 .../cellar/bundle/LocalBundleListener.java      |  2 +
 .../bundle/shell/BundleCommandSupport.java      |  4 +-
 .../bundle/shell/InstallBundleCommand.java      |  2 +
 .../cellar/bundle/shell/ListBundleCommand.java  | 34 +++++++--------
 .../resources/OSGI-INF/blueprint/blueprint.xml  |  1 -
 .../config/ConfigurationSynchronizer.java       | 20 ---------
 .../resources/OSGI-INF/blueprint/blueprint.xml  |  1 -
 .../cellar/features/FeaturesSynchronizer.java   | 26 +-----------
 .../internal/CellarBundleMBeanImpl.java         | 44 ++++++++++----------
 .../karaf/cellar/obr/ObrUrlSynchronizer.java    |  1 -
 12 files changed, 74 insertions(+), 116 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleState.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleState.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleState.java
index db2ff52..d553124 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleState.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleState.java
@@ -22,10 +22,21 @@ public class BundleState implements Serializable {
 
     private static final long serialVersionUID = 5933673686648413918L;
 
+    private long id;
     private String name;
+    private String symbolicName;
+    private String version;
     private String location;
     private int status;
 
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
     public String getName() {
         return name;
     }
@@ -34,6 +45,22 @@ public class BundleState implements Serializable {
         this.name = name;
     }
 
+    public String getSymbolicName() {
+        return symbolicName;
+    }
+
+    public void setSymbolicName(String symbolicName) {
+        this.symbolicName = symbolicName;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
     public String getLocation() {
         return location;
     }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
index fa6b2f1..9f26d1a 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
@@ -41,8 +41,6 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
 
     private static final transient Logger LOGGER = LoggerFactory.getLogger(BundleSynchronizer.class);
 
-    private EventProducer eventProducer;
-
     public void init() {
         Set<Group> groups = groupManager.listLocalGroups();
         if (groups != null && !groups.isEmpty()) {
@@ -135,12 +133,6 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
     @Override
     public void push(Group group) {
 
-        // check if the producer is ON
-        if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
-            LOGGER.debug("CELLAR BUNDLE: cluster event producer is OFF");
-            return;
-        }
-
         if (group != null) {
             String groupName = group.getName();
             LOGGER.debug("CELLAR BUNDLE: pushing bundles to cluster group {}", groupName);
@@ -154,6 +146,7 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
 
                 bundles = bundleContext.getBundles();
                 for (Bundle bundle : bundles) {
+                    long bundleId = bundle.getBundleId();
                     String symbolicName = bundle.getSymbolicName();
                     String version = bundle.getVersion().toString();
                     String bundleLocation = bundle.getLocation();
@@ -164,14 +157,16 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
                     if (isAllowed(group, Constants.CATEGORY, bundleLocation, EventType.OUTBOUND)) {
 
                         BundleState bundleState = new BundleState();
+                        bundleState.setId(bundleId);
                         // get the bundle name or location.
                         String name = (String) bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_NAME);
                         // if there is no name, then default to symbolic name.
-                        name = (name == null) ? bundle.getSymbolicName() : name;
+                        name = (name == null) ? symbolicName : name;
                         // if there is no symbolic name, resort to location.
                         name = (name == null) ? bundle.getLocation() : name;
                         bundleState.setName(name);
-                        bundleState.setName(bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_NAME));
+                        bundleState.setSymbolicName(symbolicName);
+                        bundleState.setVersion(version);
 
                         bundleState.setLocation(bundleLocation);
 
@@ -195,11 +190,6 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
                         if (existingState == null || !existingState.getLocation().equals(bundleState.getLocation()) || existingState.getStatus() != bundleState.getStatus()) {
                             // update the bundle in the cluster group
                             clusterBundles.put(id, bundleState);
-
-                            // broadcast the event
-                            ClusterBundleEvent event = new ClusterBundleEvent(symbolicName, version, bundleLocation, status);
-                            event.setSourceGroup(group);
-                            eventProducer.produce(event);
                         }
 
                     } else
@@ -234,12 +224,4 @@ public class BundleSynchronizer extends BundleSupport implements Synchronizer {
         return "disabled";
     }
 
-    public EventProducer getEventProducer() {
-        return eventProducer;
-    }
-
-    public void setEventProducer(EventProducer eventProducer) {
-        this.eventProducer = eventProducer;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
index 8b642f0..3530255 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
@@ -106,7 +106,9 @@ public class LocalBundleListener extends BundleSupport implements SynchronousBun
                                 if (state == null) {
                                     state = new BundleState();
                                 }
+                                state.setId(event.getBundle().getBundleId());
                                 state.setName(name);
+                                state.setVersion(version);
                                 state.setStatus(type);
                                 state.setLocation(bundleLocation);
                                 clusterBundles.put(symbolicName + "/" + version, state);

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BundleCommandSupport.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BundleCommandSupport.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BundleCommandSupport.java
index 5eeb6f6..d28f857 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BundleCommandSupport.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BundleCommandSupport.java
@@ -50,13 +50,11 @@ public abstract class BundleCommandSupport extends CellarCommandSupport {
             int id = -1;
             try {
                 id = Integer.parseInt(name);
-                int index = 0;
                 for (String bundle : clusterBundles.keySet()) {
-                    if (index == id) {
+                    if (clusterBundles.get(bundle).getId() == id) {
                         key = bundle;
                         break;
                     }
-                    index++;
                 }
             } catch (NumberFormatException nfe) {
                 // ignore

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
index eac7669..d2eaa95 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
@@ -98,6 +98,8 @@ public class InstallBundleCommand extends CellarCommandSupport {
                     Map<String, BundleState> clusterBundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
                     BundleState state = new BundleState();
                     state.setName(name);
+                    state.setSymbolicName(symbolicName);
+                    state.setVersion(version);
                     state.setLocation(url);
                     if (start) {
                         state.setStatus(BundleEvent.STARTED);

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
index 04996c6..6eef376 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
@@ -23,7 +23,7 @@ import org.apache.karaf.cellar.core.Group;
 import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
 import org.osgi.framework.BundleEvent;
 
-import java.util.Map;
+import java.util.*;
 
 @Command(scope = "cluster", name = "bundle-list", description = "List the bundles in a cluster group")
 public class ListBundleCommand extends CellarCommandSupport {
@@ -57,22 +57,13 @@ public class ListBundleCommand extends CellarCommandSupport {
             if (clusterBundles != null && !clusterBundles.isEmpty()) {
                 System.out.println(String.format("Bundles in cluster group " + groupName));
                 System.out.println(String.format(HEADER_FORMAT, "ID", "State", "Name"));
-                int id = 0;
-                for (String bundle : clusterBundles.keySet()) {
-                    String[] tokens = bundle.split("/");
-                    String symbolicName = null;
-                    String version = null;
-                    if (tokens.length == 2) {
-                        symbolicName = tokens[0];
-                        version = tokens[1];
-                    } else {
-                        symbolicName = bundle;
-                        version = "";
-                    }
-                    BundleState state = clusterBundles.get(bundle);
+                List<BundleState> bundles = new ArrayList<BundleState>(clusterBundles.values());
+                Collections.sort(bundles, new BundleStateComparator());
+
+                for (BundleState bundle : bundles) {
 
                     String status;
-                    switch (state.getStatus()) {
+                    switch (bundle.getStatus()) {
                         case BundleEvent.INSTALLED:
                             status = "Installed";
                             break;
@@ -99,15 +90,14 @@ public class ListBundleCommand extends CellarCommandSupport {
                             break;
                     }
                     if (showLocation) {
-                        System.out.println(String.format(OUTPUT_FORMAT, id, status, state.getLocation()));
+                        System.out.println(String.format(OUTPUT_FORMAT, bundle.getId(), status, bundle.getLocation()));
                     } else {
                         if (showSymbolicName) {
-                            System.out.println(String.format(OUTPUT_FORMAT, id, status, symbolicName + " (" + version + ")"));
+                            System.out.println(String.format(OUTPUT_FORMAT, bundle.getId(), status, bundle.getSymbolicName() + " (" + bundle.getVersion() + ")"));
                         } else {
-                            System.out.println(String.format(OUTPUT_FORMAT, id, status, state.getName() + " (" + version + ")"));
+                            System.out.println(String.format(OUTPUT_FORMAT, bundle.getId(), status, bundle.getName() + " (" + bundle.getVersion() + ")"));
                         }
                     }
-                    id++;
                 }
             } else {
                 System.err.println("No bundle found in cluster group " + groupName);
@@ -119,4 +109,10 @@ public class ListBundleCommand extends CellarCommandSupport {
         return null;
     }
 
+    class BundleStateComparator implements Comparator<BundleState> {
+        public int compare(BundleState b1, BundleState b2) {
+            return (int)(b1.getId() - b2.getId());
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 1f04eb0..cb84006 100644
--- a/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -31,7 +31,6 @@
         <property name="configurationAdmin" ref="configurationAdmin"/>
         <property name="groupManager" ref="groupManager"/>
         <property name="clusterManager" ref="clusterManager"/>
-        <property name="eventProducer" ref="eventProducer"/>
         <property name="bundleContext" ref="blueprintBundleContext"/>
         <property name="featuresService" ref="featuresService"/>
     </bean>

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java b/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
index e675de9..c257961 100644
--- a/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
+++ b/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
@@ -38,8 +38,6 @@ public class ConfigurationSynchronizer extends ConfigurationSupport implements S
 
     private static final transient Logger LOGGER = LoggerFactory.getLogger(ConfigurationSynchronizer.class);
 
-    private EventProducer eventProducer;
-
     public ConfigurationSynchronizer() {
         // nothing to do
     }
@@ -131,12 +129,6 @@ public class ConfigurationSynchronizer extends ConfigurationSupport implements S
      */
     public void push(Group group) {
 
-        // check if the producer is ON
-        if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
-            LOGGER.debug("CELLAR CONFIG: cluster event producer is OFF");
-            return;
-        }
-
         if (group != null) {
             String groupName = group.getName();
             Map<String, Properties> clusterConfigurations = clusterManager.getMap(Constants.CONFIGURATION_MAP + Configurations.SEPARATOR + groupName);
@@ -154,10 +146,6 @@ public class ConfigurationSynchronizer extends ConfigurationSupport implements S
                             localDictionary = filter(localDictionary);
                             // update the configurations in the cluster group
                             clusterConfigurations.put(pid, dictionaryToProperties(localDictionary));
-                            // broadcast the cluster event
-                            ClusterConfigurationEvent event = new ClusterConfigurationEvent(pid);
-                            event.setSourceGroup(group);
-                            eventProducer.produce(event);
                         } else
                             LOGGER.debug("CELLAR CONFIG: configuration with PID {} is marked BLOCKED OUTBOUND for cluster group {}", pid, groupName);
                     }
@@ -195,12 +183,4 @@ public class ConfigurationSynchronizer extends ConfigurationSupport implements S
         return "disabled";
     }
 
-    public EventProducer getEventProducer() {
-        return eventProducer;
-    }
-
-    public void setEventProducer(EventProducer eventProducer) {
-        this.eventProducer = eventProducer;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/config/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/config/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index d83f7e9..337f0d9 100644
--- a/config/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/config/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -33,7 +33,6 @@
         <property name="configurationAdmin" ref="configurationAdmin"/>
         <property name="groupManager" ref="groupManager"/>
         <property name="clusterManager" ref="clusterManager"/>
-        <property name="eventProducer" ref="eventProducer"/>
         <property name="storage" value="${storage}"/>
     </bean>
     <service ref="synchronizer" interface="org.apache.karaf.cellar.core.Synchronizer">

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
index afd0b59..073dc19 100644
--- a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
+++ b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
@@ -40,8 +40,6 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
 
     private static final transient Logger LOGGER = LoggerFactory.getLogger(FeaturesSynchronizer.class);
 
-    private EventProducer eventProducer;
-
     @Override
     public void init() {
         Set<Group> groups = groupManager.listLocalGroups();
@@ -160,9 +158,6 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
             String groupName = group.getName();
             LOGGER.debug("CELLAR FEATURES_MAP: pushing features repositories and features in cluster group {}.", groupName);
 
-            ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
-            try {
-                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
 
                 List<String> clusterRepositories = clusterManager.getList(Constants.REPOSITORIES_LIST + Configurations.SEPARATOR + groupName);
                 Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
@@ -192,30 +187,19 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
                 if (featuresList != null && featuresList.length > 0) {
                     for (Feature feature : featuresList) {
                         if (isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.OUTBOUND)) {
+                            LOGGER.debug("CELLAR FEATURES: pushing feature {} in cluster group {}", feature.getName(), group.getName());
                             // push the local features status to the cluster group
                             FeatureState clusterFeatureState = new FeatureState();
                             clusterFeatureState.setName(feature.getName());
                             clusterFeatureState.setVersion(feature.getVersion());
                             clusterFeatureState.setInstalled(featuresService.isInstalled(feature));
                             clusterFeatures.put(feature.getName() + "/" + feature.getVersion(), clusterFeatureState);
-                            LOGGER.debug("CELLAR FEATURES: pushing feature {} in cluster group {}", feature.getName(), group.getName());
-                            // broadcast the cluster event
-                            ClusterFeaturesEvent event;
-                            if (featuresService.isInstalled(feature)) {
-                                event = new ClusterFeaturesEvent(feature.getName(), feature.getVersion(), FeatureEvent.EventType.FeatureInstalled);
-                            } else {
-                                event = new ClusterFeaturesEvent(feature.getName(), feature.getVersion(), FeatureEvent.EventType.FeatureUninstalled);
-                            }
-                            eventProducer.produce(event);
                         } else {
                             LOGGER.debug("CELLAR FEATURES: feature {} is marked BLOCKED OUTBOUND for cluster group {}", feature.getName(), group.getName());
                         }
                     }
                 }
-            } finally {
-                Thread.currentThread().setContextClassLoader(originalClassLoader);
             }
-        }
     }
 
     /**
@@ -242,12 +226,4 @@ public class FeaturesSynchronizer extends FeaturesSupport implements Synchronize
         return "disabled";
     }
 
-    public EventProducer getEventProducer() {
-        return eventProducer;
-    }
-
-    public void setEventProducer(EventProducer eventProducer) {
-        this.eventProducer = eventProducer;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java
----------------------------------------------------------------------
diff --git a/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java b/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java
index 53e6c56..1ab2222 100644
--- a/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java
+++ b/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java
@@ -28,7 +28,7 @@ import javax.management.NotCompliantMBeanException;
 import javax.management.StandardMBean;
 import javax.management.openmbean.*;
 import java.net.URL;
-import java.util.Map;
+import java.util.*;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
 import java.util.regex.Matcher;
@@ -108,9 +108,10 @@ public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundle
         if (manifest == null) {
             throw new IllegalArgumentException("Bundle location " + location + " doesn't seem correct");
         }
-        String name = manifest.getMainAttributes().getValue("Bundle-SymbolicName");
+        String name = manifest.getMainAttributes().getValue("Bundle-Name");
+        String symbolicName = manifest.getMainAttributes().getValue("Bundle-SymbolicName");
         if (name == null) {
-            name = manifest.getMainAttributes().getValue("Bundle-SymbolicName");
+            name = symbolicName;
         }
         if (name == null) {
             name = location;
@@ -125,6 +126,8 @@ public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundle
             Map<String, BundleState> clusterBundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
             BundleState state = new BundleState();
             state.setName(name);
+            state.setVersion(version);
+            state.setSymbolicName(name);
             state.setLocation(location);
             state.setStatus(BundleEvent.INSTALLED);
             clusterBundles.put(name + "/" + version, state);
@@ -317,20 +320,12 @@ public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundle
         Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
         try {
             Map<String, BundleState> clusterBundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
-            int id = 0;
-            for (String bundle : clusterBundles.keySet()) {
-                String[] tokens = bundle.split("/");
-                String name = null;
-                String version = null;
-                if (tokens.length == 2) {
-                    name = tokens[0];
-                    version = tokens[1];
-                } else {
-                    name = bundle;
-                }
-                BundleState state = clusterBundles.get(bundle);
+            List<BundleState> bundles = new ArrayList<BundleState>(clusterBundles.values());
+            Collections.sort(bundles, new BundleStateComparator());
+
+            for (BundleState bundle : bundles) {
                 String status;
-                switch (state.getStatus()) {
+                switch (bundle.getStatus()) {
                     case BundleEvent.INSTALLED:
                         status = "Installed";
                         break;
@@ -358,9 +353,8 @@ public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundle
                 }
                 CompositeData data = new CompositeDataSupport(compositeType,
                         new String[]{"id", "name", "version", "status", "location"},
-                        new Object[]{id, name, version, status, state.getLocation()});
+                        new Object[]{bundle.getId(), bundle.getName(), bundle.getVersion(), status, bundle.getLocation()});
                 table.put(data);
-                id++;
             }
         } finally {
             Thread.currentThread().setContextClassLoader(originalClassLoader);
@@ -383,13 +377,11 @@ public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundle
             int id = -1;
             try {
                 id = Integer.parseInt(name);
-                int index = 0;
-                for (String clusterBundle : clusterBundles.keySet()) {
-                    if (index == id) {
-                        key = clusterBundle;
+                for (String bundle : clusterBundles.keySet()) {
+                    if (clusterBundles.get(bundle).getId() == id) {
+                        key = bundle;
                         break;
                     }
-                    index++;
                 }
             } catch (NumberFormatException nfe) {
                 // ignore
@@ -466,4 +458,10 @@ public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundle
         return key;
     }
 
+    class BundleStateComparator implements Comparator<BundleState> {
+        public int compare(BundleState b1, BundleState b2) {
+            return (int)(b1.getId() - b2.getId());
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/01651af8/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java b/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java
index 0cf6f04..2303349 100644
--- a/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java
+++ b/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java
@@ -126,7 +126,6 @@ public class ObrUrlSynchronizer extends ObrSupport implements Synchronizer {
                         for (Resource resource : resources) {
                             ObrBundleInfo info = new ObrBundleInfo(resource.getPresentationName(), resource.getSymbolicName(), resource.getVersion().toString());
                             clusterBundles.add(info);
-                            // TODO fire event to the other nodes ?
                         }
                     } else {
                         LOGGER.debug("CELLAR OBR: URL {} is BLOCKED OUTBOUND for cluster group {}", repository.getURI().toString(), groupName);