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 2012/01/26 16:02:19 UTC

svn commit: r1236222 - in /karaf/cellar/branches/cellar-2.2.x: ./ bundle/src/main/java/org/apache/karaf/cellar/bundle/ bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/ bund...

Author: jbonofre
Date: Thu Jan 26 15:02:18 2012
New Revision: 1236222

URL: http://svn.apache.org/viewvc?rev=1236222&view=rev
Log:
[KARAF-861] Add Cellar cluster group support for bundles

Added:
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java
      - copied, changed from r1235915, karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java
      - copied, changed from r1235915, karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java
      - copied, changed from r1235915, karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
    karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarBundleMBean.java
      - copied, changed from r1235915, karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java
    karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java
Modified:
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSupport.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
    karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java
    karaf/cellar/branches/cellar-2.2.x/management/pom.xml
    karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java
    karaf/cellar/branches/cellar-2.2.x/management/src/main/resources/OSGI-INF/blueprint/blueprint.xml
    karaf/cellar/branches/cellar-2.2.x/pom.xml
    karaf/cellar/branches/cellar-2.2.x/shell/src/main/java/org/apache/karaf/cellar/shell/group/GroupSupport.java

Modified: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java Thu Jan 26 15:02:18 2012
@@ -20,6 +20,7 @@ import org.apache.karaf.cellar.core.cont
 import org.apache.karaf.cellar.core.control.Switch;
 import org.apache.karaf.cellar.core.event.EventHandler;
 import org.apache.karaf.cellar.core.event.EventType;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleException;
 import org.slf4j.Logger;
@@ -43,11 +44,11 @@ public class BundleEventHandler extends 
      */
     public void handle(RemoteBundleEvent event) {
 
-        if (event == null || event.getSourceGroup() == null || node == null || node.equals(event.getSourceNode()))
-            return;
-
         Group group = event.getSourceGroup();
-        String groupName = group.getName();
+        String groupName = "";
+        if (group != null) {
+            groupName = group.getName();
+        }
         String bundleLocation = event.getLocation();
 
         Map<String, BundleState> bundleTable = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
@@ -56,12 +57,15 @@ public class BundleEventHandler extends 
             //Check if the pid is marked as local.
             if (isAllowed(event.getSourceGroup(), Constants.CATEGORY, bundleLocation, EventType.INBOUND)) {
                 BundleState state = new BundleState();
-                state.setLocation(event.getLocation());
                 state.setStatus(event.getType());
 
                 if (event.getType() == BundleEvent.INSTALLED) {
                     LOGGER.debug("CELLAR BUNDLE: installing bundle {} from {}", event.getId(), event.getLocation());
-                    installBundleFromLocation(event.getLocation());
+                    Bundle bundle = installBundleFromLocation(event.getLocation());
+                    state.setLocation(event.getLocation());
+                    event.setSymbolicName(bundle.getSymbolicName());
+                    event.setVersion(bundle.getVersion().toString());
+                    event.setId(bundle.getSymbolicName() + "/" + bundle.getVersion());
                     bundleTable.put(event.getId(), state);
                 } else if (event.getType() == BundleEvent.UNINSTALLED) {
                     LOGGER.debug("CELLAR BUNDLE: un-installing bundle {}/{}", event.getSymbolicName(), event.getVersion());
@@ -69,12 +73,14 @@ public class BundleEventHandler extends 
                     bundleTable.remove(event.getId());
                 } else if (event.getType() == BundleEvent.STARTED) {
                     LOGGER.debug("CELLAR BUNDLE: starting bundle {}/{}", event.getSymbolicName(), event.getVersion());
-                    startBundle(event.getSymbolicName(), event.getVersion());
+                    Bundle bundle = startBundle(event.getSymbolicName(), event.getVersion());
+                    state.setLocation(bundle.getLocation());
                     bundleTable.put(event.getId(), state);
                 } else if (event.getType() == BundleEvent.STOPPED) {
                     LOGGER.debug("CELLAR BUNDLE: stopping bundle {}/{}", event.getSymbolicName(), event.getVersion());
-                    stopBundle(event.getSymbolicName(), event.getVersion());
+                    Bundle bundle = stopBundle(event.getSymbolicName(), event.getVersion());
                     state.setStatus(BundleEvent.INSTALLED);
+                    state.setLocation(bundle.getLocation());
                     bundleTable.put(event.getId(), state);
                 } else if (event.getType() == BundleEvent.UPDATED) {
                     LOGGER.debug("CELLAR BUNDLE: updating bundle {}/{}", event.getSymbolicName(), event.getVersion());

Modified: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSupport.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSupport.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSupport.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSupport.java Thu Jan 26 15:02:18 2012
@@ -51,8 +51,8 @@ public class BundleSupport extends Cella
     /**
      * Installs a bundle using its location.
      */
-    public void installBundleFromLocation(String location) throws BundleException {
-        getBundleContext().installBundle(location);
+    public Bundle installBundleFromLocation(String location) throws BundleException {
+        return getBundleContext().installBundle(location);
     }
 
     /**
@@ -80,15 +80,17 @@ public class BundleSupport extends Cella
      * @param version
      * @throws BundleException
      */
-    public void startBundle(String symbolicName, String version) throws BundleException {
+    public Bundle startBundle(String symbolicName, String version) throws BundleException {
         Bundle[] bundles = getBundleContext().getBundles();
         if (bundles != null) {
             for (Bundle bundle : bundles) {
                 if (bundle.getSymbolicName().equals(symbolicName) && bundle.getVersion().toString().equals(version)) {
                     bundle.start();
+                    return bundle;
                 }
             }
         }
+        return null;
     }
 
     /**
@@ -98,15 +100,17 @@ public class BundleSupport extends Cella
      * @param version
      * @throws BundleException
      */
-    public void stopBundle(String symbolicName, String version) throws BundleException {
+    public Bundle stopBundle(String symbolicName, String version) throws BundleException {
         Bundle[] bundles = getBundleContext().getBundles();
         if (bundles != null) {
             for (Bundle bundle : bundles) {
                 if (bundle.getSymbolicName().equals(symbolicName) && bundle.getVersion().toString().equals(version)) {
                     bundle.stop();
+                    return bundle;
                 }
             }
         }
+        return null;
     }
 
     /**

Modified: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java Thu Jan 26 15:02:18 2012
@@ -77,7 +77,7 @@ public class BundleSynchronizer extends 
                 String[] tokens = id.split("/");
                 String symbolicName = tokens[0];
                 String version = tokens[1];
-                if (tokens != null && tokens.length > 2) {
+                if (tokens != null && tokens.length == 2) {
                     if (state != null) {
                         String bundleLocation = state.getLocation();
                         if (isAllowed(group, Constants.CATEGORY, bundleLocation, EventType.INBOUND)) {

Modified: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java Thu Jan 26 15:02:18 2012
@@ -18,7 +18,4 @@ public class Constants {
     public static final String CATEGORY = "bundle";
     public static final String BUNDLE_MAP = "org.apache.karaf.cellar.bundle.map";
 
-    private Constants() {
-    }
-
 }

Modified: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java Thu Jan 26 15:02:18 2012
@@ -45,7 +45,7 @@ public class LocalBundleListener extends
                 try {
                     groups = groupManager.listLocalGroups();
                 } catch (Exception ex) {
-                    LOGGER.warn("Failed to list local groups. Is Cellar uninstalling?");
+                    LOGGER.warn("Failed to list local groups. Is Cellar uninstalling ?");
                 }
 
                 if (groups != null && !groups.isEmpty()) {

Added: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java?rev=1236222&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java Thu Jan 26 15:02:18 2012
@@ -0,0 +1,68 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.cellar.bundle.shell;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.cellar.bundle.BundleState;
+import org.apache.karaf.cellar.bundle.Constants;
+import org.apache.karaf.cellar.bundle.RemoteBundleEvent;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.event.EventProducer;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.osgi.framework.BundleEvent;
+
+import java.net.URL;
+import java.util.Map;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+@Command(scope = "cluster", name = "bundle-install", description = "Install a bundle to a cluster group")
+public class InstallBundleCommand extends CellarCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
+    String groupName;
+    
+    @Argument(index = 1, name = "location", description = "The bundle location", required = true, multiValued = false)
+    String location;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        // get the name and version in the location MANIFEST
+        JarInputStream jarInputStream = new JarInputStream(new URL(location).openStream());
+        Manifest manifest = jarInputStream.getManifest();
+        String name = manifest.getMainAttributes().getValue("Bundle-SymbolicName");
+        String version = manifest.getMainAttributes().getValue("Bundle-Version");
+        jarInputStream.close();
+
+        // populate the cluster map
+        Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+        BundleState state = new BundleState();
+        state.setLocation(location);
+        state.setStatus(BundleEvent.INSTALLED);
+        bundles.put(name + "/" + version, state);
+        
+        // send the event
+        Group group = groupManager.findGroupByName(groupName);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, location, BundleEvent.INSTALLED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+
+        return null;
+    }
+
+}

Added: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java?rev=1236222&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java Thu Jan 26 15:02:18 2012
@@ -0,0 +1,71 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.cellar.bundle.shell;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.cellar.bundle.BundleState;
+import org.apache.karaf.cellar.bundle.Constants;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.osgi.framework.BundleEvent;
+
+import java.util.Map;
+
+@Command(scope = "cluster", name = "bundle-list", description = "List the bundles that are assigned to a cluster group")
+public class ListBundleCommand extends CellarCommandSupport {
+    
+    protected static final String OUTPUT_FORMAT = "%-50s %-20s %-15s %-20s";
+
+    @Argument(index = 0, name = "group", description = "The name of the cluster group", required = true, multiValued = false)
+    String groupName;
+    
+    @Override
+    protected Object doExecute() throws Exception {
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+            
+            Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+            if (bundles != null && !bundles.isEmpty()) {
+                System.out.println(String.format("Bundles for group: " + groupName));
+                System.out.println(String.format(OUTPUT_FORMAT, "Name", "Version", "Status", "Location"));
+                for (String bundle : bundles.keySet()) {
+                    String[] tokens = bundle.split("/");
+                    String name = tokens[0];
+                    String version = tokens[1];
+                    BundleState state = bundles.get(bundle);
+                    String status;
+                    switch (state.getStatus()) {
+                        case BundleEvent.INSTALLED: status = "Installed"; break;
+                        case BundleEvent.RESOLVED: status = "Resolved"; break;
+                        case BundleEvent.STARTED: status = "Started"; break;
+                        case BundleEvent.STARTING: status = "Starting"; break;
+                        case BundleEvent.STOPPED: status = "Stopped"; break;
+                        case BundleEvent.STOPPING: status = "Stopping"; break;
+                        case BundleEvent.UNINSTALLED: status = "Uninstalled"; break;
+                        default: status = ""; break;
+                    }
+                    System.out.println(String.format(OUTPUT_FORMAT, name, version, status, state.getLocation()));
+                }
+            } else {
+                System.err.println("No bundles found for group: " + groupName);
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+        return null;
+    }
+    
+}

Copied: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java (from r1235915, karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java)
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java?p2=karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java&p1=karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java&r1=1235915&r2=1236222&rev=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java Thu Jan 26 15:02:18 2012
@@ -11,41 +11,38 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.cellar.features.shell;
+package org.apache.karaf.cellar.bundle.shell;
 
-import org.apache.karaf.cellar.core.Group;
-import org.apache.karaf.cellar.core.event.EventProducer;
-import org.apache.karaf.cellar.features.RemoteFeaturesEvent;
 import org.apache.felix.gogo.commands.Argument;
 import org.apache.felix.gogo.commands.Command;
-import org.apache.karaf.features.FeatureEvent;
-
-/**
- * Install feature command.
- */
-@Command(scope = "cluster", name = "features-install", description = "Installs a feature to the cluster group")
-public class InstallFeatureCommand extends FeatureCommandSupport {
+import org.apache.karaf.cellar.bundle.RemoteBundleEvent;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.event.EventProducer;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.osgi.framework.BundleEvent;
 
-    @Argument(index = 0, name = "group", description = "The name of the group", required = true, multiValued = false)
+@Command(scope = "cluster", name = "bundle-start", description = "Start a bundle on a given cluster group")
+public class StartBundleCommand extends CellarCommandSupport {
+    
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
     String groupName;
+    
+    @Argument(index = 1, name = "name", description = "The bundle symbolic name", required = true, multiValued = false)
+    String name;
 
-    @Argument(index = 1, name = "feature", description = "The name of the feature", required = true, multiValued = false)
-    String feature;
-
-    @Argument(index = 2, name = "version", description = "The version of the feature", required = false, multiValued = false)
+    @Argument(index = 2, name = "version", description = "The bundle version", required = true, multiValued = false)
     String version;
-
+    
     @Override
     protected Object doExecute() throws Exception {
         Group group = groupManager.findGroupByName(groupName);
-        EventProducer producer = eventTransportFactory.getEventProducer(groupName,true);
-        RemoteFeaturesEvent event = new RemoteFeaturesEvent(feature, version, FeatureEvent.EventType.FeatureInstalled);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, null, BundleEvent.STARTED);
         event.setForce(true);
         event.setSourceGroup(group);
         producer.produce(event);
-
-        updateFeatureStatus(groupName, feature, version, true);
+        
         return null;
     }
-
+    
 }

Copied: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java (from r1235915, karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java)
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java?p2=karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java&p1=karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java&r1=1235915&r2=1236222&rev=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java Thu Jan 26 15:02:18 2012
@@ -11,40 +11,37 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.cellar.features.shell;
+package org.apache.karaf.cellar.bundle.shell;
 
-import org.apache.karaf.cellar.core.Group;
-import org.apache.karaf.cellar.core.event.EventProducer;
-import org.apache.karaf.cellar.features.RemoteFeaturesEvent;
 import org.apache.felix.gogo.commands.Argument;
 import org.apache.felix.gogo.commands.Command;
-import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.cellar.bundle.RemoteBundleEvent;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.event.EventProducer;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.osgi.framework.BundleEvent;
 
-/**
- * Install feature command.
- */
-@Command(scope = "cluster", name = "features-install", description = "Installs a feature to the cluster group")
-public class InstallFeatureCommand extends FeatureCommandSupport {
+@Command(scope = "cluster", name = "bundle-stop", description = "Stop a bundle on the given cluster group")
+public class StopBundleCommand extends CellarCommandSupport {
 
-    @Argument(index = 0, name = "group", description = "The name of the group", required = true, multiValued = false)
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
     String groupName;
-
-    @Argument(index = 1, name = "feature", description = "The name of the feature", required = true, multiValued = false)
-    String feature;
-
-    @Argument(index = 2, name = "version", description = "The version of the feature", required = false, multiValued = false)
+    
+    @Argument(index = 1, name = "name", description = "The bundle symbolic name", required = true, multiValued = false)
+    String name;
+    
+    @Argument(index = 2, name = "version", description = "The bundle version", required = true, multiValued = false)
     String version;
 
     @Override
     protected Object doExecute() throws Exception {
         Group group = groupManager.findGroupByName(groupName);
-        EventProducer producer = eventTransportFactory.getEventProducer(groupName,true);
-        RemoteFeaturesEvent event = new RemoteFeaturesEvent(feature, version, FeatureEvent.EventType.FeatureInstalled);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, null, BundleEvent.STOPPED);
         event.setForce(true);
         event.setSourceGroup(group);
         producer.produce(event);
 
-        updateFeatureStatus(groupName, feature, version, true);
         return null;
     }
 

Copied: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java (from r1235915, karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java)
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java?p2=karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java&p1=karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java&r1=1235915&r2=1236222&rev=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java Thu Jan 26 15:02:18 2012
@@ -11,41 +11,38 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.cellar.features.shell;
+package org.apache.karaf.cellar.bundle.shell;
 
-import org.apache.karaf.cellar.core.Group;
-import org.apache.karaf.cellar.core.event.EventProducer;
-import org.apache.karaf.cellar.features.RemoteFeaturesEvent;
 import org.apache.felix.gogo.commands.Argument;
 import org.apache.felix.gogo.commands.Command;
-import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.cellar.bundle.RemoteBundleEvent;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.event.EventProducer;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.osgi.framework.BundleEvent;
 
-/**
- * Install feature command.
- */
-@Command(scope = "cluster", name = "features-install", description = "Installs a feature to the cluster group")
-public class InstallFeatureCommand extends FeatureCommandSupport {
+@Command(scope = "cluster", name = "bundle-uninstall", description = "Uninstall a bundle from a cluster group")
+public class UninstallBundleCommand extends CellarCommandSupport {
 
-    @Argument(index = 0, name = "group", description = "The name of the group", required = true, multiValued = false)
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
     String groupName;
 
-    @Argument(index = 1, name = "feature", description = "The name of the feature", required = true, multiValued = false)
-    String feature;
+    @Argument(index = 1, name = "name", description = "The bundle symbolic name", required = true, multiValued = false)
+    String name;
 
-    @Argument(index = 2, name = "version", description = "The version of the feature", required = false, multiValued = false)
+    @Argument(index = 2, name = "version", description = "The bundle version", required = true, multiValued = false)
     String version;
-
+    
     @Override
     protected Object doExecute() throws Exception {
         Group group = groupManager.findGroupByName(groupName);
-        EventProducer producer = eventTransportFactory.getEventProducer(groupName,true);
-        RemoteFeaturesEvent event = new RemoteFeaturesEvent(feature, version, FeatureEvent.EventType.FeatureInstalled);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, null, BundleEvent.UNINSTALLED);
         event.setForce(true);
         event.setSourceGroup(group);
         producer.produce(event);
 
-        updateFeatureStatus(groupName, feature, version, true);
         return null;
     }
-
+    
 }

Added: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java?rev=1236222&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java Thu Jan 26 15:02:18 2012
@@ -0,0 +1,46 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.cellar.bundle.shell.completers;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import java.util.List;
+
+/**
+ * Completer on all bundle symbolic name.
+ */
+public class AllBundlesNameCompleter implements Completer {
+    
+    private BundleContext bundleContext;
+    
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        for (Bundle bundle : bundleContext.getBundles()) {
+            delegate.getStrings().add(bundle.getSymbolicName());
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+    
+    public BundleContext getBundleContext() {
+        return this.bundleContext;
+    }
+    
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+    
+}

Added: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java?rev=1236222&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java Thu Jan 26 15:02:18 2012
@@ -0,0 +1,46 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.cellar.bundle.shell.completers;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import java.util.List;
+
+/**
+ * Completer on all bundle version..
+ */
+public class AllBundlesVersionCompleter implements Completer {
+
+    private BundleContext bundleContext;
+
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        for (Bundle bundle : bundleContext.getBundles()) {
+            delegate.getStrings().add(bundle.getVersion().toString());
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+
+    public BundleContext getBundleContext() {
+        return this.bundleContext;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+}

Modified: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml (original)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml Thu Jan 26 15:02:18 2012
@@ -51,6 +51,8 @@
     <reference id="clusterManager" interface="org.apache.karaf.cellar.core.ClusterManager"/>
     <reference id="groupManager" interface="org.apache.karaf.cellar.core.GroupManager"/>
     <reference id="configurationAdmin" interface="org.osgi.service.cm.ConfigurationAdmin"/>
+    <reference id="eventTransportFactory" interface="org.apache.karaf.cellar.core.event.EventTransportFactory"/>
+    <reference id="eventProducer" interface="org.apache.karaf.cellar.core.event.EventProducer"/>
     <reference-list id="groupEventProducers" member-type="service-object"
                     interface="org.apache.karaf.cellar.core.event.EventProducer" filter="(type=group)"/>
 

Added: karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml?rev=1236222&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml (added)
+++ karaf/cellar/branches/cellar-2.2.x/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml Thu Jan 26 15:02:18 2012
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">
+
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
+        <command name="cluster/bundle-list">
+            <action class="org.apache.karaf.cellar.bundle.shell.ListBundleCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+            </completers>
+        </command>
+        <command name="cluster/bundle-install">
+            <action class="org.apache.karaf.cellar.bundle.shell.InstallBundleCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+            </completers>
+        </command>
+        <command name="cluster/bundle-uninstall">
+            <action class="org.apache.karaf.cellar.bundle.shell.UninstallBundleCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <ref component-id="allBundlesNameCompleter"/>
+                <ref component-id="allBundlesVersionCompleter"/>
+            </completers>
+        </command>
+        <command name="cluster/bundle-start">
+            <action class="org.apache.karaf.cellar.bundle.shell.StartBundleCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <ref component-id="allBundlesNameCompleter"/>
+                <ref component-id="allBundlesVersionCompleter"/>
+            </completers>
+        </command>
+        <command name="cluster/bundle-stop">
+            <action class="org.apache.karaf.cellar.bundle.shell.StopBundleCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <ref component-id="allBundlesNameCompleter"/>
+                <ref component-id="allBundlesVersionCompleter"/>
+            </completers>
+        </command>
+    </command-bundle>
+
+    <bean id="allGroupCompleter" class="org.apache.karaf.cellar.core.shell.completer.AllGroupsCompleter">
+        <property name="groupManager" ref="groupManager"/>
+    </bean>
+    
+    <bean id="allBundlesNameCompleter" class="org.apache.karaf.cellar.bundle.shell.completers.AllBundlesNameCompleter">
+        <property name="bundleContext" ref="blueprintBundleContext"/>
+    </bean>
+
+    <bean id="allBundlesVersionCompleter" class="org.apache.karaf.cellar.bundle.shell.completers.AllBundlesVersionCompleter">
+        <property name="bundleContext" ref="blueprintBundleContext"/>
+    </bean>    
+
+</blueprint>
\ No newline at end of file

Modified: karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/shell/InstallFeatureCommand.java Thu Jan 26 15:02:18 2012
@@ -38,7 +38,7 @@ public class InstallFeatureCommand exten
     @Override
     protected Object doExecute() throws Exception {
         Group group = groupManager.findGroupByName(groupName);
-        EventProducer producer = eventTransportFactory.getEventProducer(groupName,true);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
         RemoteFeaturesEvent event = new RemoteFeaturesEvent(feature, version, FeatureEvent.EventType.FeatureInstalled);
         event.setForce(true);
         event.setSourceGroup(group);

Modified: karaf/cellar/branches/cellar-2.2.x/management/pom.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/management/pom.xml?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/management/pom.xml (original)
+++ karaf/cellar/branches/cellar-2.2.x/management/pom.xml Thu Jan 26 15:02:18 2012
@@ -44,6 +44,7 @@
             org.apache.karaf.management*;version="[2,4)",
             org.apache.karaf.features*;version="[2,4)",
             org.apache.karaf.cellar*;version="${project.version}",
+            org.apache.karaf.cellar.bundle*;version="${project.version}",
             org.apache.karaf.cellar.config*;version="${project.version}",
             org.apache.karaf.cellar.core*;version="${project.version}",
             org.apache.karaf.cellar.features*;version="${project.version}",
@@ -59,6 +60,10 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.karaf.cellar</groupId>
+            <artifactId>org.apache.karaf.cellar.bundle</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.cellar</groupId>
             <artifactId>org.apache.karaf.cellar.config</artifactId>
         </dependency>
         <dependency>

Copied: karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarBundleMBean.java (from r1235915, karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java)
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarBundleMBean.java?p2=karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarBundleMBean.java&p1=karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java&r1=1235915&r2=1236222&rev=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarBundleMBean.java Thu Jan 26 15:02:18 2012
@@ -16,14 +16,15 @@ package org.apache.karaf.cellar.manageme
 import javax.management.openmbean.TabularData;
 
 /**
- *  MBean interface describing the operations and attributes on a Cellar feature.
+ * MBean interface describing the operations and attributes on Cellar bundles.
  */
-public interface CellarFeaturesMBean {
-
-    void install(String group, String name) throws Exception;
-    void install(String group, String name, String version) throws Exception;
-    void uninstall(String group, String name) throws Exception;
-    void uninstall(String group, String name, String version) throws Exception;
-    TabularData getFeatures(String group) throws Exception;
-
+public interface CellarBundleMBean {
+    
+    void install(String group, String location) throws Exception;
+    void uninstall(String group, String symbolicName, String version) throws Exception;
+    void start(String group, String symbolicName, String version) throws Exception;
+    void stop(String group, String symbolicName, String version) throws Exception;
+    
+    TabularData getBundles(String group) throws Exception;
+    
 }

Modified: karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/CellarFeaturesMBean.java Thu Jan 26 15:02:18 2012
@@ -24,6 +24,7 @@ public interface CellarFeaturesMBean {
     void install(String group, String name, String version) throws Exception;
     void uninstall(String group, String name) throws Exception;
     void uninstall(String group, String name, String version) throws Exception;
+
     TabularData getFeatures(String group) throws Exception;
 
 }

Added: karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java?rev=1236222&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/management/src/main/java/org/apache/karaf/cellar/management/internal/CellarBundleMBeanImpl.java Thu Jan 26 15:02:18 2012
@@ -0,0 +1,154 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.cellar.management.internal;
+
+import org.apache.karaf.cellar.bundle.BundleState;
+import org.apache.karaf.cellar.bundle.Constants;
+import org.apache.karaf.cellar.bundle.RemoteBundleEvent;
+import org.apache.karaf.cellar.core.ClusterManager;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.GroupManager;
+import org.apache.karaf.cellar.core.event.EventProducer;
+import org.apache.karaf.cellar.core.event.EventTransportFactory;
+import org.apache.karaf.cellar.management.CellarBundleMBean;
+import org.osgi.framework.BundleEvent;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.*;
+import java.net.URL;
+import java.util.Map;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+/**
+ * Implementation of the Cellar bundle MBean.
+ */
+public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundleMBean {
+    
+    private ClusterManager clusterManager;
+    private EventTransportFactory eventTransportFactory;
+    private GroupManager groupManager;
+
+    public CellarBundleMBeanImpl() throws NotCompliantMBeanException {
+        super(CellarBundleMBean.class);
+    }
+    
+    public ClusterManager getClusterManager() {
+        return this.clusterManager;
+    }
+
+    public void setClusterManager(ClusterManager clusterManager) {
+        this.clusterManager = clusterManager;
+    }
+
+    public EventTransportFactory getEventTransportFactory() {
+        return this.eventTransportFactory;
+    }
+
+    public void setEventTransportFactory(EventTransportFactory eventTransportFactory) {
+        this.eventTransportFactory = eventTransportFactory;
+    }
+
+    public GroupManager getGroupManager() {
+        return this.groupManager;
+    }
+    
+    public void setGroupManager(GroupManager groupManager) {
+        this.groupManager = groupManager;
+    }
+    
+    public void install(String groupName, String location) throws Exception {
+        // get the name and version in the location MANIFEST
+        JarInputStream jarInputStream = new JarInputStream(new URL(location).openStream());
+        Manifest manifest = jarInputStream.getManifest();
+        String name = manifest.getMainAttributes().getValue("Bundle-SymbolicName");
+        String version = manifest.getMainAttributes().getValue("Bundle-Version");
+        jarInputStream.close();
+
+        // populate the cluster map
+        Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+        BundleState state = new BundleState();
+        state.setLocation(location);
+        state.setStatus(BundleEvent.INSTALLED);
+        bundles.put(name + "/" + version, state);
+
+        // send the event
+        Group group = groupManager.findGroupByName(groupName);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, location, BundleEvent.INSTALLED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+    }
+    
+    public void uninstall(String groupName, String symbolicName, String version) throws Exception {
+        Group group = groupManager.findGroupByName(groupName);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(symbolicName, version, null, BundleEvent.UNINSTALLED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);        
+    }
+    
+    public void start(String groupName, String symbolicName, String version) throws Exception {
+        Group group = groupManager.findGroupByName(groupName);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(symbolicName, version, null, BundleEvent.STARTED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);        
+    }
+    
+    public void stop(String groupName, String symbolicName, String version) throws Exception {
+        Group group = groupManager.findGroupByName(groupName);
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(symbolicName, version, null, BundleEvent.STOPPED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);        
+    }
+    
+    public TabularData getBundles(String groupName) throws Exception {
+        CompositeType compositeType = new CompositeType("Bundle", "Karaf Cellar bundle",
+                new String[]{ "name", "version", "status", "location"},
+                new String[]{ "Name of the bundle", "Version of the bundle", "Current status of the bundle", "Location of the bundle"},
+                new OpenType[]{ SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING });
+        TabularType tableType = new TabularType("Bundles", "Table of all KarafCellar bundles", compositeType,
+                new String[]{ "name", "version" });
+        TabularData table = new TabularDataSupport(tableType);
+
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+        try {
+            Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+            for (String bundle : bundles.keySet()) {
+                String[] tokens = bundle.split("/");
+                String name = tokens[0];
+                String version = tokens[1];
+                BundleState state = bundles.get(bundle);
+                CompositeData data = new CompositeDataSupport(compositeType,
+                        new String[]{ "name", "version", "status", "location"},
+                        new Object[]{ name, version, state.getStatus(), state.getLocation()});
+                table.put(data);
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+        
+        return table;
+    }
+
+}

Modified: karaf/cellar/branches/cellar-2.2.x/management/src/main/resources/OSGI-INF/blueprint/blueprint.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/management/src/main/resources/OSGI-INF/blueprint/blueprint.xml?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/management/src/main/resources/OSGI-INF/blueprint/blueprint.xml (original)
+++ karaf/cellar/branches/cellar-2.2.x/management/src/main/resources/OSGI-INF/blueprint/blueprint.xml Thu Jan 26 15:02:18 2012
@@ -49,6 +49,12 @@
         <property name="executionContext" ref="executionContext"/>
         <property name="groupManager" ref="groupManager"/>
     </bean>
+    
+    <bean id="cellarBundleMBean" class="org.apache.karaf.cellar.management.internal.CellarBundleMBeanImpl">
+        <property name="clusterManager" ref="clusterManager"/>
+        <property name="eventTransportFactory" ref="eventTransportFactory"/>
+        <property name="groupManager" ref="groupManager"/>
+    </bean>
 
     <bean id="mbeanRegister" class="org.apache.karaf.management.MBeanRegistrer">
         <property name="mbeans">
@@ -57,6 +63,7 @@
                 <entry value="org.apache.karaf.cellar:type=node,name=${karaf.name}" key-ref="cellarNodeMBean"/>
                 <entry value="org.apache.karaf.cellar:type=config,name=${karaf.name}" key-ref="cellarConfigMBean"/>
                 <entry value="org.apache.karaf.cellar:type=features,name=${karaf.name}" key-ref="cellarFeaturesMBean"/>
+                <entry value="org.apache.karaf.cellar:type=bundle,name=${karaf.name}" key-ref="cellarBundleMBean"/>
                 <entry value="org.apache.karaf.cellar:type=group,name=${karaf.name}" key-ref="cellarGroupMBean"/>
             </map>
         </property>

Modified: karaf/cellar/branches/cellar-2.2.x/pom.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/pom.xml?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/pom.xml (original)
+++ karaf/cellar/branches/cellar-2.2.x/pom.xml Thu Jan 26 15:02:18 2012
@@ -118,6 +118,11 @@
             <!-- Cellar -->
             <dependency>
                 <groupId>org.apache.karaf.cellar</groupId>
+                <artifactId>org.apache.karaf.cellar.bundle</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.karaf.cellar</groupId>
                 <artifactId>org.apache.karaf.cellar.config</artifactId>
                 <version>${project.version}</version>
             </dependency>

Modified: karaf/cellar/branches/cellar-2.2.x/shell/src/main/java/org/apache/karaf/cellar/shell/group/GroupSupport.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/shell/src/main/java/org/apache/karaf/cellar/shell/group/GroupSupport.java?rev=1236222&r1=1236221&r2=1236222&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/shell/src/main/java/org/apache/karaf/cellar/shell/group/GroupSupport.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/shell/src/main/java/org/apache/karaf/cellar/shell/group/GroupSupport.java Thu Jan 26 15:02:18 2012
@@ -34,6 +34,7 @@ public abstract class GroupSupport exten
 
     /**
      * Executes the command.
+     *
      * @param action
      * @param group
      * @param nodes
@@ -41,19 +42,20 @@ public abstract class GroupSupport exten
      * @throws Exception
      */
     protected Object doExecute(ManageGroupAction action, String group, Collection<String> nodes) throws Exception {
-     return doExecute(action,group,nodes,true);
+        return doExecute(action, group, nodes, true);
     }
 
     /**
      * Executes the command.
+     *
      * @param action
      * @param group
      * @param nodes
-     * @param supressOutput
+     * @param suppressOutput
      * @return
      * @throws Exception
      */
-    protected Object doExecute(ManageGroupAction action, String group, Collection<String> nodes,Boolean supressOutput) throws Exception {
+    protected Object doExecute(ManageGroupAction action, String group, Collection<String> nodes, Boolean suppressOutput) throws Exception {
         ManageGroupCommand command = new ManageGroupCommand(clusterManager.generateId());
         Set<Node> recipientList = clusterManager.listNodes(nodes);
 
@@ -73,29 +75,29 @@ public abstract class GroupSupport exten
         }
 
         Map<Node, ManageGroupResult> results = executionContext.execute(command);
-        if(!supressOutput) {
-        if (results == null || results.isEmpty()) {
-            System.out.println("No result received within given timeout");
-        } else {
-            System.out.println(String.format(OUTPUT_FORMAT, " ", "Node", "Group"));
-            for (Node node : results.keySet()) {
-                ManageGroupResult result = results.get(node);
-                if (result != null && result.getGroups() != null) {
-                    for (Group g : result.getGroups()) {
-                        if (g.getNodes() != null && !g.getNodes().isEmpty()) {
-                            for (Node memeber : g.getNodes()) {
-                                String name = g.getName();
-                                String mark = " ";
-                                if (memeber.equals(clusterManager.getNode()))
-                                    mark = "*";
-                                System.out.println(String.format(OUTPUT_FORMAT, mark, memeber.getId(), name));
-                            }
-                        } else System.out.println(String.format(OUTPUT_FORMAT, "", "", g.getName()));
+        if (!suppressOutput) {
+            if (results == null || results.isEmpty()) {
+                System.out.println("No result received within given timeout");
+            } else {
+                System.out.println(String.format(OUTPUT_FORMAT, " ", "Node", "Group"));
+                for (Node node : results.keySet()) {
+                    ManageGroupResult result = results.get(node);
+                    if (result != null && result.getGroups() != null) {
+                        for (Group g : result.getGroups()) {
+                            if (g.getNodes() != null && !g.getNodes().isEmpty()) {
+                                for (Node memeber : g.getNodes()) {
+                                    String name = g.getName();
+                                    String mark = " ";
+                                    if (memeber.equals(clusterManager.getNode()))
+                                        mark = "*";
+                                    System.out.println(String.format(OUTPUT_FORMAT, mark, memeber.getId(), name));
+                                }
+                            } else System.out.println(String.format(OUTPUT_FORMAT, "", "", g.getName()));
+                        }
                     }
                 }
             }
         }
-        }
         return null;
     }