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/02/01 08:22:20 UTC

svn commit: r1238955 - in /karaf/cellar/trunk: 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/ bundle/src/main/resourc...

Author: jbonofre
Date: Wed Feb  1 07:22:19 2012
New Revision: 1238955

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

Added:
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java
    karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
    karaf/cellar/trunk/itests/src/test/java/org/apache/karaf/cellar/itests/CellarBundleTest.java
Modified:
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java
    karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
    karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml

Modified: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java?rev=1238955&r1=1238954&r2=1238955&view=diff
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java (original)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleEventHandler.java Wed Feb  1 07:22:19 2012
@@ -43,38 +43,20 @@ 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 bundleLocation = event.getLocation();
-
-        Map<String, BundleState> bundleTable = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
-
         try {
             //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 (isAllowed(event.getSourceGroup(), Constants.CATEGORY, event.getLocation(), EventType.INBOUND)) {
                 if (event.getType() == BundleEvent.INSTALLED) {
                     installBundleFromLocation(event.getLocation());
-                    bundleTable.put(event.getId(), state);
                     LOGGER.debug("CELLAR BUNDLE: installing {}/{}", event.getSymbolicName(), event.getVersion());
                 } else if (event.getType() == BundleEvent.UNINSTALLED) {
                     uninstallBundle(event.getSymbolicName(), event.getVersion());
-                    bundleTable.remove(event.getId());
                     LOGGER.debug("CELLAR BUNDLE: uninstalling {}/{}", event.getSymbolicName(), event.getVersion());
                 } else if (event.getType() == BundleEvent.STARTED) {
                     startBundle(event.getSymbolicName(), event.getVersion());
-                    bundleTable.put(event.getId(), state);
                     LOGGER.debug("CELLAR BUNDLE: starting {}/{}", event.getSymbolicName(), event.getVersion());
                 } else if (event.getType() == BundleEvent.STOPPED) {
                     stopBundle(event.getSymbolicName(), event.getVersion());
-                    state.setStatus(BundleEvent.INSTALLED);
-                    bundleTable.put(event.getId(), state);
                     LOGGER.debug("CELLAR BUNDLE: stopping {}/{}", event.getSymbolicName(), event.getVersion());
                 } else if (event.getType() == BundleEvent.UPDATED) {
                     updateBundle(event.getSymbolicName(), event.getVersion());

Modified: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java?rev=1238955&r1=1238954&r2=1238955&view=diff
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java (original)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java Wed Feb  1 07:22:19 2012
@@ -84,9 +84,9 @@ public class BundleSynchronizer extends 
                             try {
                                 if (state.getStatus() == BundleEvent.INSTALLED) {
                                     installBundleFromLocation(state.getLocation());
-                                    startBundle(symbolicName, version);
                                 } else if (state.getStatus() == BundleEvent.STARTED) {
                                     installBundleFromLocation(state.getLocation());
+                                    startBundle(symbolicName, version);
                                 }
                             } catch (BundleException e) {
                                 LOGGER.error("CELLAR BUNDLE: error while pulling bundle", e);
@@ -99,7 +99,7 @@ public class BundleSynchronizer extends 
     }
 
     /**
-     * Publishses local configuration to the cluster.
+     * Publishes local configuration to the cluster.
      */
     public void push(Group group) {
 
@@ -128,9 +128,11 @@ public class BundleSynchronizer extends 
                     RemoteBundleEvent event = null;
                     if (existingState == null) {
                         event = new RemoteBundleEvent(symbolicName, version, bundleLocation, status);
-                    } else if (bundleState.getStatus() == BundleEvent.STARTED) {
-                        event = new RemoteBundleEvent(symbolicName, version, bundleLocation, status);
+                        // update the cluster map
+                        bundleTable.put(id, bundleState);
                     }
+
+                    // broadcast the event
                     if (producerList != null && !producerList.isEmpty() && event != null) {
                         for (EventProducer producer : producerList) {
                             producer.produce(event);

Modified: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java?rev=1238955&r1=1238954&r2=1238955&view=diff
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java (original)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/Constants.java Wed Feb  1 07:22:19 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/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java?rev=1238955&r1=1238954&r2=1238955&view=diff
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java (original)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/LocalBundleListener.java Wed Feb  1 07:22:19 2012
@@ -13,6 +13,7 @@
  */
 package org.apache.karaf.cellar.bundle;
 
+import org.apache.karaf.cellar.core.Configurations;
 import org.apache.karaf.cellar.core.Group;
 import org.apache.karaf.cellar.core.Node;
 import org.apache.karaf.cellar.core.event.EventProducer;
@@ -23,6 +24,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public class LocalBundleListener extends BundleSupport implements BundleListener {
@@ -45,29 +47,39 @@ 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()) {
                     for (Group group : groups) {
 
                         String symbolicName = event.getBundle().getSymbolicName();
-
-                        if (symbolicName != null) {
-                            String version = event.getBundle().getVersion().toString();
-                            String bundleLocation = event.getBundle().getLocation();
-                            int type = event.getType();
-                            if (isAllowed(group, Constants.CATEGORY, bundleLocation, EventType.OUTBOUND)) {
-                                RemoteBundleEvent remoteBundleEvent = new RemoteBundleEvent(symbolicName, version, bundleLocation, type);
-                                remoteBundleEvent.setSourceGroup(group);
-                                remoteBundleEvent.setSourceNode(node);
-                                if (producerList != null && !producerList.isEmpty()) {
-                                    for (EventProducer producer : producerList) {
-                                        producer.produce(remoteBundleEvent);
-                                    }
+                        String version = event.getBundle().getVersion().toString();
+                        String bundleLocation = event.getBundle().getLocation();
+                        int type = event.getType();
+
+                        if (isAllowed(group, Constants.CATEGORY, bundleLocation, EventType.OUTBOUND)) {
+                            RemoteBundleEvent remoteBundleEvent = new RemoteBundleEvent(symbolicName, version, bundleLocation, type);
+                            remoteBundleEvent.setSourceGroup(group);
+                            remoteBundleEvent.setSourceNode(node);
+
+                            // update the cluster map
+                            Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + group.getName());
+                            BundleState state = bundles.get(symbolicName + "/" + version);
+                            if (state == null) {
+                                state = new BundleState();
+                            }
+                            state.setStatus(type);
+                            state.setLocation(event.getBundle().getLocation());
+                            bundles.put(symbolicName + "/" + version, state);
+
+                            // broadcast the cluster event
+                            if (producerList != null && !producerList.isEmpty()) {
+                                for (EventProducer producer : producerList) {
+                                    producer.produce(remoteBundleEvent);
                                 }
-                            } else LOGGER.debug("CELLAR BUNDLE: bundle {} is marked as BLOCKED OUTBOUND", symbolicName);
-                        } else LOGGER.debug("CELLAR BUNDLE: artifact is not a bundle");
+                            }
+                        } else LOGGER.debug("CELLAR BUNDLE: bundle {} is marked as BLOCKED OUTBOUND", symbolicName);
                     }
                 }
             }

Added: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java (added)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/InstallBundleCommand.java Wed Feb  1 07:22:19 2012
@@ -0,0 +1,74 @@
+/*
+ * 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 assigned 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 {
+        Group group = groupManager.findGroupByName(groupName);
+
+        if (group == null) {
+            System.err.println("Cluster group " + groupName + " does't exist");
+            return null;
+        }
+
+        // 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);
+
+        // broadcast the event
+        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/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java (added)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/ListBundleCommand.java Wed Feb  1 07:22:19 2012
@@ -0,0 +1,94 @@
+/*
+ * 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.Group;
+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 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 cluster group name.", required = true, multiValued = false)
+    String groupName;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        Group group = groupManager.findGroupByName(groupName);
+
+        if (group == null) {
+            System.err.println("Cluster group " + groupName + " doesn't exist");
+            return null;
+        }
+
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+        try {
+            Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+            if (bundles != null && !bundles.isEmpty()) {
+                System.out.println(String.format("Bundles for cluster 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 cluster group: " + groupName);
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+        return null;
+    }
+
+}

Added: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java (added)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StartBundleCommand.java Wed Feb  1 07:22:19 2012
@@ -0,0 +1,76 @@
+/*
+ * 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.util.Map;
+
+@Command(scope = "cluster", name = "bundle-start", description = "Start a bundle assigned to a 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 = 2, name = "version", description = "The bundle version.", required = true, multiValued = false)
+    String version;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        Group group = groupManager.findGroupByName(groupName);
+
+        if (group == null) {
+            System.err.println("Group " + groupName + " doesn't exist");
+            return null;
+        }
+
+        // update the distributed map
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+        try {
+            Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+            BundleState state = bundles.get(name + "/" + version);
+            if (state == null) {
+                System.err.println("Bundle " + name + "/" + version + " not found in cluster group " + groupName);
+                return null;
+            }
+            state.setStatus(BundleEvent.STARTED);
+            bundles.put(name + "/" + version, state);
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+
+        // broadcast the event
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, null, BundleEvent.STARTED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+
+        return null;
+    }
+
+}

Added: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java (added)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/StopBundleCommand.java Wed Feb  1 07:22:19 2012
@@ -0,0 +1,76 @@
+/*
+ * 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.util.Map;
+
+@Command(scope = "cluster", name = "bundle-stop", description = "Stop a bundle assigned to a cluster group.")
+public class StopBundleCommand 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 = 2, name = "version", description = "The bundle version.", required = true, multiValued = false)
+    String version;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        Group group = groupManager.findGroupByName(groupName);
+
+        if (group == null) {
+            System.err.println("Cluster group " + groupName + " doesn't exist");
+            return null;
+        }
+
+        // update the cluster map
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+        try {
+            Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+            BundleState state = bundles.get(name + "/" + version);
+            if (state == null) {
+                System.err.println("Bundle " + name + "/" + version + " not found in cluster group " + groupName);
+                return null;
+            }
+            state.setStatus(BundleEvent.STOPPED);
+            bundles.put(name + "/" + version, state);
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+
+        // broadcast the event
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, null, BundleEvent.STOPPED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+
+        return null;
+    }
+
+}

Added: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java (added)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/UninstallBundleCommand.java Wed Feb  1 07:22:19 2012
@@ -0,0 +1,75 @@
+/*
+ * 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.util.Map;
+
+@Command(scope = "cluster", name = "bundle-uninstall", description = "Uninstall a bundle assigned to a cluster group.")
+public class UninstallBundleCommand 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 = 2, name = "version", description = "The bundle version.", required = true, multiValued = false)
+    String version;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        Group group = groupManager.findGroupByName(groupName);
+
+        if (group == null) {
+            System.err.println("Cluster group " + groupName + " doesn't exist");
+            return null;
+        }
+
+        // update the cluster map
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+        try {
+            Map<String, BundleState> bundles = clusterManager.getMap(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName);
+            BundleState state = bundles.get(name + "/" + version);
+            if (state == null) {
+                System.err.println("Bundle " + name + "/" + version + " not found in cluster group " + groupName);
+                return null;
+            }
+            bundles.remove(name + "/" + version);
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+
+        // broadcast the event
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        RemoteBundleEvent event = new RemoteBundleEvent(name, version, null, BundleEvent.UNINSTALLED);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+
+        return null;
+    }
+
+}

Added: karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java (added)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesNameCompleter.java Wed Feb  1 07:22:19 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/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java (added)
+++ karaf/cellar/trunk/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/completers/AllBundlesVersionCompleter.java Wed Feb  1 07:22:19 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/trunk/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml?rev=1238955&r1=1238954&r2=1238955&view=diff
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml (original)
+++ karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml Wed Feb  1 07:22:19 2012
@@ -48,10 +48,13 @@
             <entry key="managed" value="true"/>
         </service-properties>
     </service>
+    <service ref="synchronizer" interface="org.apache.karaf.cellar.core.Synchronizer"/>
 
     <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/trunk/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml (added)
+++ karaf/cellar/trunk/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml Wed Feb  1 07:22:19 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

Added: karaf/cellar/trunk/itests/src/test/java/org/apache/karaf/cellar/itests/CellarBundleTest.java
URL: http://svn.apache.org/viewvc/karaf/cellar/trunk/itests/src/test/java/org/apache/karaf/cellar/itests/CellarBundleTest.java?rev=1238955&view=auto
==============================================================================
--- karaf/cellar/trunk/itests/src/test/java/org/apache/karaf/cellar/itests/CellarBundleTest.java (added)
+++ karaf/cellar/trunk/itests/src/test/java/org/apache/karaf/cellar/itests/CellarBundleTest.java Wed Feb  1 07:22:19 2012
@@ -0,0 +1,60 @@
+/*
+ * 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.itests;
+
+import org.apache.karaf.cellar.core.ClusterManager;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openengsb.labs.paxexam.karaf.options.LogLevelOption;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.ExamReactorStrategy;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactorFactory;
+
+import static org.junit.Assert.assertNotNull;
+import static org.openengsb.labs.paxexam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
+import static org.openengsb.labs.paxexam.karaf.options.KarafDistributionOption.logLevel;
+
+@RunWith(JUnit4TestRunner.class)
+@ExamReactorStrategy(AllConfinedStagedReactorFactory.class)
+public class CellarBundleTest extends CellarTestSupport {
+
+    @Test
+    public void testCellarBundleModule() throws Exception {
+        installCellar();
+        Thread.sleep(DEFAULT_TIMEOUT);
+        ClusterManager clusterManager = getOsgiService(ClusterManager.class);
+        assertNotNull(clusterManager);
+
+        System.err.println(executeCommand("cluster:bundle-list default"));
+    }
+
+    @After
+    public void tearDown() {
+        try {
+            unInstallCellar();
+        } catch (Exception ex) {
+            //Ignore
+        }
+    }
+
+    @Configuration
+    public Option[] config() {
+        return new Option[]{
+                cellarDistributionConfiguration(), keepRuntimeFolder(), logLevel(LogLevelOption.LogLevel.ERROR)};
+    }
+
+}