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 2011/09/16 14:49:24 UTC

svn commit: r1171529 [2/2] - in /karaf/cellar/branches/cellar-2.2.x: ./ assembly/src/main/resources/ bundle/src/main/java/org/apache/karaf/cellar/bundle/ cloud/src/main/java/org/apache/karaf/cellar/cloud/ config/src/main/java/org/apache/karaf/cellar/co...

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlEventHandler.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlEventHandler.java?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlEventHandler.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlEventHandler.java Fri Sep 16 12:49:22 2011
@@ -0,0 +1,81 @@
+/*
+ * 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.obr;
+
+import org.apache.karaf.cellar.core.control.BasicSwitch;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * OBR URL Event handler.
+ */
+public class ObrUrlEventHandler extends ObrSupport implements EventHandler<ObrUrlEvent> {
+
+    private static final transient Logger LOGGER = LoggerFactory.getLogger(ObrUrlEventHandler.class);
+
+    public static final String SWITCH_ID = "org.apache.karaf.cellar.event.obr.url";
+
+    private final Switch eventSwitch = new BasicSwitch(SWITCH_ID);
+
+    @Override
+    public void init() {
+        super.init();
+    }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+    }
+
+    /**
+     * Process an OBR URL event.
+     *
+     * @param obrUrlEvent the OBR URL Event.
+     */
+    @Override
+    public void handle(ObrUrlEvent obrUrlEvent) {
+        String url = obrUrlEvent.getUrl();
+        String groupName = obrUrlEvent.getSourceGroup().getName();
+        try {
+            if (isAllowed(obrUrlEvent.getSourceGroup(), Constants.URLS_CONFIG_CATEGORY, url, EventType.INBOUND) || obrUrlEvent.getForce()) {
+                LOGGER.debug("CELLAR OBR: received OBR URL {}", url);
+                if (obrUrlEvent.getType() == Constants.URL_ADD_EVENT_TYPE) {
+                    LOGGER.debug("CELLAR OBR: add OBR URL {}", url);
+                    obrService.addRepository(url);
+                }
+                if (obrUrlEvent.getType() == Constants.URL_REMOVE_EVENT_TYPE) {
+                    LOGGER.debug("CELLAR OBR: remove OBR URL {}", url);
+                    boolean removed = obrService.removeRepository(url);
+                    if (!removed) {
+                        LOGGER.warn("CELLAR OBR: the repository URL hasn't been removed from the OBR service");
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.error("CELLAR OBR: failed to register URL {}", url, e);
+        }
+    }
+
+    public Class<ObrUrlEvent> getType() {
+        return ObrUrlEvent.class;
+    }
+
+    public Switch getSwitch() {
+        return this.eventSwitch;
+    }
+
+}

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/ObrUrlSynchronizer.java Fri Sep 16 12:49:22 2011
@@ -0,0 +1,142 @@
+/*
+ * 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.obr;
+
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.Synchronizer;
+import org.apache.karaf.cellar.core.event.EventProducer;
+import org.osgi.service.cm.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Bootstrap synchronizer for the OBR URLs.
+ */
+public class ObrUrlSynchronizer extends ObrSupport implements Synchronizer {
+
+    private static final transient Logger LOGGER = LoggerFactory.getLogger(ObrUrlSynchronizer.class);
+
+    private List<EventProducer> producerList;
+
+    public void init() {
+        super.init();
+        Set<Group> groups = groupManager.listLocalGroups();
+        if (groups != null && !groups.isEmpty()) {
+            for (Group group : groups) {
+                if (isSyncEnabled(group)) {
+                    LOGGER.debug("CELLAR OBR: synchronize group {}", group.getName());
+                    pull(group);
+                    push(group);
+                } else LOGGER.warn("CELLAR OBR: synchronize is not enabled for group {}", group.getName());
+            }
+        }
+    }
+
+    public void destroy() {
+        super.destroy();
+    }
+
+    /**
+     * Pull the OBR URL from the cluster.
+     *
+     * @param group the cluster group.
+     */
+    public void pull(Group group) {
+        if (group != null) {
+            String groupName = group.getName();
+            Set<String> urls = clusterManager.getSet(Constants.URLS_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+            ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+            try {
+                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+                if (urls != null && !urls.isEmpty()) {
+                    for (String url : urls) {
+                        try {
+                            obrService.addRepository(url);
+                            LOGGER.debug("CELLAR OBR: add OBR repository URL {}", url);
+                        } catch (Exception e) {
+                            LOGGER.error("CELLAR OBR: unable to add the OBR repository URL {}", url, e);
+                        }
+                    }
+                }
+            } finally {
+                Thread.currentThread().setContextClassLoader(originalClassLoader);
+            }
+        }
+    }
+
+    /**
+     * Push the local OBR URLs to the cluster
+     *
+     * @param group the cluster group.
+     */
+    public void push(Group group) {
+        if (group != null) {
+            String groupName = group.getName();
+            Set<String> urls = clusterManager.getSet(Constants.URLS_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+
+            ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+            try {
+                Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+                Repository[] repositories = obrService.listRepositories();
+                for (Repository repository : repositories) {
+                    urls.add(repository.getURI().toString());
+                    // push the bundles in the OBR distributed set
+                    Set<ObrBundleInfo> bundles = clusterManager.getSet(Constants.BUNDLES_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+                    Resource[] resources = repository.getResources();
+                    for (Resource resource : resources) {
+                        ObrBundleInfo info = new ObrBundleInfo(resource.getPresentationName(),resource.getSymbolicName(), resource.getVersion().toString());
+                        bundles.add(info);
+                    }
+                    // TODO fire event to the other nodes ?
+                }
+            } finally {
+                Thread.currentThread().setContextClassLoader(originalClassLoader);
+            }
+        }
+    }
+
+    @Override
+    public Boolean isSyncEnabled(Group group) {
+        Boolean result = Boolean.FALSE;
+        String groupName = group.getName();
+
+        try {
+            Configuration configuration = configurationAdmin.getConfiguration(Configurations.GROUP);
+            Dictionary<String, String> properties = configuration.getProperties();
+            String propertyKey = groupName + Configurations.SEPARATOR + Constants.URLS_CONFIG_CATEGORY + Configurations.SEPARATOR + Configurations.SYNC;
+            String propertyValue = properties.get(propertyKey);
+            result = Boolean.parseBoolean(propertyValue);
+        } catch (IOException e) {
+            LOGGER.error("CELLAR OBR: error while checking if sync is enabled", e);
+        }
+        return result;
+    }
+
+    public List<EventProducer> getProducerList() {
+        return producerList;
+    }
+
+    public void setProducerList(List<EventProducer> producerList) {
+        this.producerList = producerList;
+    }
+
+}

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrAddUrlCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrAddUrlCommand.java?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrAddUrlCommand.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrAddUrlCommand.java Fri Sep 16 12:49:22 2011
@@ -0,0 +1,67 @@
+/*
+ * 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.obr.shell;
+
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+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.obr.Constants;
+import org.apache.karaf.cellar.obr.ObrBundleInfo;
+import org.apache.karaf.cellar.obr.ObrUrlEvent;
+
+import java.util.Set;
+
+/**
+ * cluster:obr-addurl command.
+ */
+@Command(scope = "cluster", name = "obr-addurl", description = "Register a repository URL in the distributed OBR service")
+public class ObrAddUrlCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
+    String groupName;
+
+    @Argument(index = 1, name = "url", description = "The repository URL to register in the OBR service", required = true, multiValued = false)
+    String url;
+
+    public Object doExecute() throws Exception {
+        // find group for the given name
+        Group group = groupManager.findGroupByName(groupName);
+        // create an event and produce it
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        ObrUrlEvent event = new ObrUrlEvent(url, Constants.URL_ADD_EVENT_TYPE);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+        // push the OBR URL in the distributed set
+        Set<String> urls = clusterManager.getSet(Constants.URLS_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+        urls.add(url);
+        // push the bundles in the OBR distributed set
+        Set<ObrBundleInfo> bundles = clusterManager.getSet(Constants.BUNDLES_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+        synchronized(obrService) {
+            Repository repository = obrService.addRepository(url);
+            Resource[] resources = repository.getResources();
+            for (Resource resource : resources) {
+                ObrBundleInfo info = new ObrBundleInfo(resource.getPresentationName(),resource.getSymbolicName(), resource.getVersion().toString());
+                bundles.add(info);
+            }
+            obrService.removeRepository(url);
+        }
+        return null;
+    }
+
+}

Copied: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrCommandSupport.java (from r1169779, karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/Constants.java)
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrCommandSupport.java?p2=karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrCommandSupport.java&p1=karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/Constants.java&r1=1169779&r2=1171529&rev=1171529&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/features/src/main/java/org/apache/karaf/cellar/features/Constants.java (original)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrCommandSupport.java Fri Sep 16 12:49:22 2011
@@ -11,16 +11,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.cellar.features;
+package org.apache.karaf.cellar.obr.shell;
 
-/**
- * Features constants.
- */
-public class Constants {
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+
+public abstract class ObrCommandSupport extends CellarCommandSupport {
+
+    protected RepositoryAdmin obrService;
+
+    public RepositoryAdmin getObrService() {
+        return this.obrService;
+    }
+
+    public void setObrService(RepositoryAdmin obrService) {
+        this.obrService = obrService;
+    }
 
-    public static final String REPOSITORIES = "org.apache.karaf.cellar.repositories";
-    public static final String FEATURES = "org.apache.karaf.cellar.features";
-    public static final String REPOSITORIES_CATEGORY = "repositories";
-    public static final String FEATURES_CATEGORY = "features";
+    public abstract Object doExecute() throws Exception;
 
 }

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrDeployCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrDeployCommand.java?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrDeployCommand.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrDeployCommand.java Fri Sep 16 12:49:22 2011
@@ -0,0 +1,59 @@
+/*
+ * 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.obr.shell;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+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.event.EventType;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.apache.karaf.cellar.obr.Constants;
+import org.apache.karaf.cellar.obr.ObrBundleEvent;
+
+import java.util.Set;
+
+/**
+ * Deploy a bundle from the OBR.
+ */
+@Command(scope = "cluster", name = "obr-deploy", description = "Deploy a bundle from the OBR on a cluster group")
+public class ObrDeployCommand extends CellarCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "The cluster group where to deploy the bundle from the OBR", required = true, multiValued = false)
+    String groupName;
+
+    @Argument(index = 1, name="bundleId", description = "The bundle ID (symbolicname,version in the OBR) to deploy", required = true, multiValued = false)
+    String bundleId;
+
+    @Option(name = "-s", aliases = { "--start" }, description = "Start the deployed bundles", required = false, multiValued = false)
+    boolean start = false;
+
+    @Override
+    protected Object doExecute() throws Exception {
+        // find the group for the given name
+        Group group = groupManager.findGroupByName(groupName);
+        // create an event and produce it
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        int type = 0;
+        if (start) type = Constants.BUNDLE_START_EVENT_TYPE;
+        ObrBundleEvent event = new ObrBundleEvent(bundleId, type);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+        return null;
+    }
+
+}

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListCommand.java?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListCommand.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListCommand.java Fri Sep 16 12:49:22 2011
@@ -0,0 +1,65 @@
+/*
+ * 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.obr.shell;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.apache.karaf.cellar.obr.Constants;
+import org.apache.karaf.cellar.obr.ObrBundleInfo;
+
+import java.util.Set;
+
+/**
+ * cluster:obr-list command.
+ */
+@Command(scope = "cluster", name = "obr-list", description = "List available bundles in the OBR of all nodes of the same cluster group.")
+public class ObrListCommand extends CellarCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
+    String groupName;
+
+    public Object doExecute() {
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+
+        try {
+            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+
+            Set<ObrBundleInfo> bundles = clusterManager.getSet(Constants.BUNDLES_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+            int maxPName = 4;
+            int maxSName = 13;
+            int maxVersion = 7;
+            for (ObrBundleInfo bundle : bundles) {
+                maxPName = Math.max(maxPName, emptyIfNull(bundle.getPresentationName()).length());
+                maxSName = Math.max(maxSName, emptyIfNull(bundle.getSymbolicName()).length());
+                maxVersion = Math.max(maxVersion, emptyIfNull(bundle.getVersion()).length());
+            }
+            String formatHeader = "  %-" + maxPName + "s  %-" + maxSName + "s   %-" + maxVersion + "s";
+            String formatLine = "[%-" + maxPName + "s] [%-" + maxSName + "s] [%-" + maxVersion + "s]";
+            System.out.println(String.format(formatHeader, "NAME", "SYMBOLIC NAME", "VERSION"));
+            for (ObrBundleInfo bundle : bundles) {
+                System.out.println(String.format(formatLine, emptyIfNull(bundle.getPresentationName()), emptyIfNull(bundle.getSymbolicName()), emptyIfNull(bundle.getVersion())));
+            }
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+        return null;
+    }
+
+    private String emptyIfNull(Object st) {
+        return st == null ? "" : st.toString();
+    }
+
+}

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListUrlCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListUrlCommand.java?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListUrlCommand.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrListUrlCommand.java Fri Sep 16 12:49:22 2011
@@ -0,0 +1,44 @@
+/*
+ * 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.obr.shell;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.apache.karaf.cellar.obr.Constants;
+
+import java.util.Set;
+
+/**
+ * cluster:obr-list command
+ */
+@Command(scope = "cluster", name = "obr-listurl", description = "List repository URLs defined in the distributed OBR service for the given group")
+public class ObrListUrlCommand extends CellarCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "Cluster group name", required = true, multiValued = false)
+    String groupName;
+
+    public Object doExecute() throws Exception {
+        // get the URLs from the distribution set
+        Set<String> urls = clusterManager.getSet(Constants.URLS_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+        if (urls != null) {
+            for (String url : urls) {
+                System.out.println(url);
+            }
+        }
+        return null;
+    }
+
+}

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrRemoveUrlCommand.java
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrRemoveUrlCommand.java?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrRemoveUrlCommand.java (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/java/org/apache/karaf/cellar/obr/shell/ObrRemoveUrlCommand.java Fri Sep 16 12:49:22 2011
@@ -0,0 +1,67 @@
+/*
+ * 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.obr.shell;
+
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+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.obr.Constants;
+import org.apache.karaf.cellar.obr.ObrBundleInfo;
+import org.apache.karaf.cellar.obr.ObrUrlEvent;
+
+import java.util.Set;
+
+/**
+ * cluster:obr-removeurl command
+ */
+@Command(scope = "cluster", name = "obr-removeurl", description = "Remove a repository URL from the distributed OBR service")
+public class ObrRemoveUrlCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
+    String groupName;
+
+    @Argument(index = 1, name = "url", description = "The repository URL to add in the OBR service", required = true, multiValued = false)
+    String url;
+
+    public Object doExecute() throws Exception {
+        // find the group for the given name
+        Group group = groupManager.findGroupByName(groupName);
+        // create an event and produce it
+        EventProducer producer = eventTransportFactory.getEventProducer(groupName, true);
+        ObrUrlEvent event = new ObrUrlEvent(url, Constants.URL_REMOVE_EVENT_TYPE);
+        event.setForce(true);
+        event.setSourceGroup(group);
+        producer.produce(event);
+        // remove URL from the distributed map
+        Set<String> urls = clusterManager.getSet(Constants.URLS_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+        urls.remove(url);
+        // remove bundles from the distributed map
+        Set<ObrBundleInfo> bundles = clusterManager.getSet(Constants.BUNDLES_DISTRIBUTED_SET_NAME + Configurations.SEPARATOR + groupName);
+        synchronized(obrService) {
+            Repository repository = obrService.addRepository(url);
+            Resource[] resources = repository.getResources();
+            for (Resource resource : resources) {
+                ObrBundleInfo info = new ObrBundleInfo(resource.getPresentationName(),resource.getSymbolicName(), resource.getVersion().toString());
+                bundles.remove(info);
+            }
+            obrService.removeRepository(url);
+        }
+        return null;
+    }
+
+}

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml Fri Sep 16 12:49:22 2011
@@ -0,0 +1,70 @@
+<?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">
+
+    <!-- OBR Bundles Event Handler -->
+    <bean id="obrBundleEventHandler" class="org.apache.karaf.cellar.obr.ObrBundleEventHandler"
+            init-method="init" destroy-method="destroy">
+        <property name="obrService" ref="repositoryAdmin"/>
+        <property name="clusterManager" ref="clusterManager"/>
+        <property name="groupManager" ref="groupManager"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+    </bean>
+
+    <!-- OBR URL Synchronizer -->
+    <bean id="obrUrlSynchronizer" class="org.apache.karaf.cellar.obr.ObrUrlSynchronizer"
+            init-method="init" destroy-method="destroy">
+        <property name="obrService" ref="repositoryAdmin"/>
+        <property name="clusterManager" ref="clusterManager"/>
+        <property name="groupManager" ref="groupManager"/>
+        <property name="producerList" ref="groupEventProducers"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+    </bean>
+
+    <!-- OBR URL Event Handler -->
+    <bean id="obrUrlEventHandler" class="org.apache.karaf.cellar.obr.ObrUrlEventHandler"
+          init-method="init" destroy-method="destroy">
+        <property name="obrService" ref="repositoryAdmin"/>
+        <property name="clusterManager" ref="clusterManager"/>
+        <property name="groupManager" ref="groupManager"/>
+        <property name="configurationAdmin" ref="configurationAdmin"/>
+    </bean>
+
+    <!-- OBR Bundle Event Handler OSGi service -->
+    <service ref="obrBundleEventHandler" interface="org.apache.karaf.cellar.core.event.EventHandler">
+        <service-properties>
+            <entry key="managed" value="true"/>
+        </service-properties>
+    </service>
+
+    <!-- OBR OSGi service -->
+    <service ref="obrUrlSynchronizer" interface="org.apache.karaf.cellar.core.Synchronizer"/>
+    <service ref="obrUrlEventHandler" interface="org.apache.karaf.cellar.core.event.EventHandler">
+        <service-properties>
+            <entry key="managed" value="true"/>
+        </service-properties>
+    </service>
+
+    <!-- service references -->
+    <reference id="repositoryAdmin" interface="org.apache.felix.bundlerepository.RepositoryAdmin"/>
+    <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)"/>
+
+</blueprint>
\ No newline at end of file

Added: karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/shell-commands.xml
URL: http://svn.apache.org/viewvc/karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/shell-commands.xml?rev=1171529&view=auto
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/shell-commands.xml (added)
+++ karaf/cellar/branches/cellar-2.2.x/obr/src/main/resources/OSGI-INF/blueprint/shell-commands.xml Fri Sep 16 12:49:22 2011
@@ -0,0 +1,82 @@
+<?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 -->
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
+        <command name="cluster/obr-list">
+            <action class="org.apache.karaf.cellar.obr.shell.ObrListCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="cluster/obr-deploy">
+            <action class="org.apache.karaf.cellar.obr.shell.ObrDeployCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="cluster/obr-listurl">
+            <action class="org.apache.karaf.cellar.obr.shell.ObrListUrlCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="cluster/obr-addurl">
+            <action class="org.apache.karaf.cellar.obr.shell.ObrAddUrlCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+                <property name="obrService" ref="repositoryAdmin"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="cluster/obr-removeurl">
+            <action class="org.apache.karaf.cellar.obr.shell.ObrRemoveUrlCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="eventTransportFactory" ref="eventTransportFactory"/>
+                <property name="obrService" ref="repositoryAdmin"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupCompleter"/>
+                <null/>
+            </completers>
+        </command>
+    </command-bundle>
+
+    <bean id="allGroupCompleter" class="org.apache.karaf.cellar.core.shell.completer.AllGroupsCompleter">
+        <property name="groupManager" ref="groupManager"/>
+    </bean>
+
+</blueprint>
\ No newline at end of file

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=1171529&r1=1171528&r2=1171529&view=diff
==============================================================================
--- karaf/cellar/branches/cellar-2.2.x/pom.xml (original)
+++ karaf/cellar/branches/cellar-2.2.x/pom.xml Fri Sep 16 12:49:22 2011
@@ -35,6 +35,7 @@
 
     <properties>
         <easymock.version>2.4</easymock.version>
+        <felix.bundlerepository.version>1.6.6</felix.bundlerepository.version>
         <felix.configadmin.version>1.2.8</felix.configadmin.version>
         <felix.webconsole.version>3.1.8</felix.webconsole.version>
         <hazelcast.version>1.9.4</hazelcast.version>
@@ -56,6 +57,7 @@
         <module>config</module>
         <module>features</module>
         <module>bundle</module>
+        <module>obr</module>
         <module>dosgi</module>
         <module>shell</module>
         <module>hazelcast</module>        
@@ -203,6 +205,11 @@
             <!-- Felix -->
             <dependency>
                 <groupId>org.apache.felix</groupId>
+                <artifactId>org.apache.felix.bundlerepository</artifactId>
+                <version>${felix.bundlerepository.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.felix</groupId>
                 <artifactId>org.apache.felix.configadmin</artifactId>
                 <version>${felix.configadmin.version}</version>
             </dependency>