You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by br...@apache.org on 2013/05/29 12:22:04 UTC

svn commit: r1487431 [2/2] - in /ace/sandbox/bramk: ./ cnf/ cnf/bin/ cnf/buildrepo/ cnf/buildrepo/biz.aQute.junit/ cnf/buildrepo/biz.aQute.launcher/ cnf/buildrepo/ee.foundation/ cnf/buildrepo/ee.minimum/ cnf/buildrepo/junit.osgi/ cnf/buildrepo/org.easy...

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/Main.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/Main.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/Main.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/Main.java Wed May 29 10:22:01 2013
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.ace.cli.command.AbstractCommand;
+import org.apache.ace.cli.command.CopyResources;
+import org.apache.ace.cli.command.CreateArtifacts;
+import org.apache.ace.cli.command.CreateDistribution;
+import org.apache.ace.cli.command.CreateFeature;
+import org.apache.ace.cli.command.CreateTarget;
+import org.apache.ace.cli.command.DeleteArtifacts;
+import org.apache.ace.cli.command.DeleteResources;
+import org.apache.ace.cli.command.ListArtifacts;
+import org.apache.ace.cli.command.ListDistributions;
+import org.apache.ace.cli.command.ListFeatures;
+import org.apache.ace.cli.command.ListResources;
+import org.apache.ace.cli.command.ListTargets;
+import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+
+/**
+ * Main class for Apache ACE cli.
+ * 
+ */
+public class Main {
+
+    private final static List<AbstractCommand> COMMANDS = new ArrayList<AbstractCommand>();
+    static {
+        COMMANDS.add(new ListResources());
+        COMMANDS.add(new DeleteResources());
+        COMMANDS.add(new CopyResources());
+        COMMANDS.add(new ListArtifacts());
+        COMMANDS.add(new CreateArtifacts());
+        COMMANDS.add(new DeleteArtifacts());
+        COMMANDS.add(new CreateArtifacts());
+        COMMANDS.add(new CreateFeature());
+        COMMANDS.add(new CreateDistribution());
+        COMMANDS.add(new CreateTarget());
+        COMMANDS.add(new ListFeatures());
+        COMMANDS.add(new ListDistributions());
+        COMMANDS.add(new ListTargets());
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        Options options = getOptions();
+        CommandLineParser parser = new BasicParser();
+        CommandLine commandLine = null;
+        try {
+            commandLine = parser.parse(options, args);
+        }
+        catch (ParseException e) {
+            System.err.println("Invalid options. Use -h for usage information.");
+            System.exit(1);
+        }
+
+        if (commandLine.hasOption("h")) {
+            printHelp(options);
+            System.exit(0);
+        }
+
+        String[] commandArgs = commandLine.getArgs();
+        if (commandArgs.length != 1) {
+            System.err.println("Invalid arguments. Use -h for usage information.");
+            System.exit(1);
+        }
+
+        String commandArg = commandArgs[0];
+        AbstractCommand command = null;
+        for (AbstractCommand candidate : COMMANDS) {
+            if (candidate.getName().equals(commandArg)) {
+                command = candidate;
+                break;
+            }
+        }
+        if (command == null) {
+            System.err.println("Unknown command. Use -h for usage information.");
+            System.exit(1);
+        }
+
+        boolean verbose = commandLine.hasOption("v");
+
+        Properties properties = loadProperties(verbose, commandLine);
+        File workdir = determineWorkdir(verbose, properties);
+        Map<String, FixedIndexedRepo> repositories = loadRepositories(properties, workdir);
+
+        Map<String, String> configuration = new HashMap<String, String>();
+        if (commandLine.hasOption("f")) {
+            configuration.put("filter", commandLine.getOptionValue("f"));
+        }
+
+        if (commandLine.hasOption("assign-name")) {
+            configuration.put("assign-name", commandLine.getOptionValue("assign-name"));
+        }
+        if (commandLine.hasOption("assign-attrs")) {
+            configuration.put("assign-attrs", commandLine.getOptionValue("assign-attrs"));
+        }
+        if (commandLine.hasOption("assign-tags")) {
+            configuration.put("assign-tags", commandLine.getOptionValue("assign-tags"));
+        }
+
+        if (commandLine.hasOption("r") && commandLine.getOptionValue("r").equals("source")) {
+            configuration.put("repository", "source");
+        }
+        else {
+            configuration.put("repository", "target");
+        }
+
+        try {
+            command.execute(commandArg, configuration, repositories, verbose);
+        }
+        catch (Exception e) {
+            System.err.println(e.getMessage());
+            System.exit(1);
+        }
+        System.exit(0);
+    }
+
+    @SuppressWarnings("static-access")
+    private static Options getOptions() {
+        Options options = new Options();
+        options.addOption("v", "verbose", false, "verbose logging");
+        options.addOption("c", "config", true, "repositories configuration file");
+        options.addOption("h", "help", false, "print this message");
+        options.addOption("f", "filter", true, "<[<namespace>:]<filter>>, default namespace is osgi.identity");
+        options.addOption("r", "repository", true, "<source|target>, default is target");
+
+        options.addOption(OptionBuilder
+            .withLongOpt("assign-name").hasArg()
+            .withDescription("assign name to feature")
+            .create());
+
+        options.addOption(OptionBuilder
+            .withLongOpt("assign-attrs").hasArg()
+            .withDescription("assign attributes <<key=value>[,<key=value>]")
+            .create());
+
+        options.addOption(OptionBuilder
+            .withLongOpt("assign-tags").hasArg()
+            .withDescription("assign tags <<key=value>[,<key=value>]")
+            .create());
+        return options;
+    }
+
+    private static void printHelp(Options options) {
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.setWidth(180);
+        formatter.printHelp("java -jar org.apache.ace.obr.client [options] <command>", options);
+
+        StringBuilder footerBuilder = new StringBuilder().append("\ncommands:");
+        for (AbstractCommand command : COMMANDS) {
+            footerBuilder.append("\n").append(command.getName()).append(" - ").append(command.getDescription());
+        }
+        footerBuilder.append("\n");
+
+        footerBuilder.append("\nconfig:\n");
+        footerBuilder.append("source.class=aQute.bnd.deployer.repository.FixedIndexedRepo\n");
+        footerBuilder.append("source.type=R5\n");
+        footerBuilder.append("source.locations=http://repository.amdatu.org/release/index.xml\n");
+        footerBuilder.append("target.class=org.apache.ace.obr.repository.AceObrRepository\n");
+        footerBuilder.append("target.type=OBR\n");
+        footerBuilder.append("target.locations=http://localhost:8080/obr/repository.xml\n");
+        footerBuilder.append("\nexamples:\n");
+        footerBuilder.append("java -jar org.apache.ace.cli.jar -c repository.properties -f \"(osgi.identity=org.apache.ace.*)\" list-resources\n");
+        System.out.println(footerBuilder.toString());
+    }
+
+    private static Map<String, FixedIndexedRepo> loadRepositories(Properties properties, File workdir) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+        Map<String, FixedIndexedRepo> repositories = new HashMap<String, FixedIndexedRepo>();
+        for (String repositoryName : new String[] { "source", "target" }) {
+
+            Map<String, String> repositoryProps = new HashMap<String, String>();
+            for (Entry<Object, Object> entry : properties.entrySet()) {
+                String key = entry.getKey().toString();
+                String value = entry.getValue().toString();
+                if (key.startsWith(repositoryName + ".")) {
+                    repositoryProps.put(key.replaceFirst(repositoryName + ".", ""), value);
+                }
+            }
+            String repoClass = repositoryProps.get("class");
+            FixedIndexedRepo repository = (FixedIndexedRepo) Main.class.getClassLoader().loadClass(repoClass).newInstance();
+            repository.setProperties(repositoryProps);
+
+            File repoWorkDir = new File(workdir, repositoryName);
+            repoWorkDir.mkdir();
+            repository.setCacheDirectory(repoWorkDir);
+            repositories.put(repositoryName, repository);
+        }
+        return repositories;
+    }
+
+    private static File determineWorkdir(boolean verbose, Properties properties) {
+        File workdir = null;
+        if (properties.get("workdir") != null) {
+            workdir = new File(properties.get("workdir").toString());
+            if (workdir.exists() && workdir.isFile()) {
+                System.err.println("Workdir is not a directory: " + workdir.getAbsolutePath());
+                System.exit(1);
+            }
+            if (!workdir.exists() && !workdir.mkdirs()) {
+                System.err.println("Failed to create directory: " + workdir.getAbsolutePath());
+                System.exit(1);
+            }
+            if (verbose) {
+                System.out.println("Using configured workdir: " + workdir.getAbsolutePath());
+            }
+        }
+        else {
+            workdir = new File(".clientcache");
+            if (!workdir.exists() && !workdir.mkdirs()) {
+                System.err.println("Failed to create directory: " + workdir.getAbsolutePath());
+                System.exit(1);
+            }
+            if (verbose) {
+                System.out.println("Using default workdir: " + workdir.getAbsolutePath());
+            }
+        }
+        return workdir;
+    }
+
+    private static Properties loadProperties(boolean verbose, CommandLine commandLine) throws IOException {
+        if (commandLine.hasOption("c")) {
+            File file = new File(commandLine.getOptionValue("c"));
+            if (!file.canRead()) {
+                throw new IOException("Cannot acces configuration file: " + commandLine.getOptionValue("c"));
+            }
+            Properties properties = new Properties();
+            InputStream inStream = new FileInputStream(file);
+            try {
+                properties.load(inStream);
+                if (verbose) {
+                    System.out.println("Loaded properties from " + commandLine.getOptionValue("c"));
+                }
+                return properties;
+            }
+            finally {
+                inStream.close();
+            }
+        }
+        return new Properties();
+    }
+
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractClientCommand.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractClientCommand.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractClientCommand.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractClientCommand.java Wed May 29 10:22:01 2013
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.amdatu.ace.client.AceClient;
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.AbstractBuilder;
+import org.amdatu.ace.client.model.AbstractResource;
+import org.amdatu.ace.client.model.Artifact;
+import org.apache.ace.cli.repository.AceObrRepository;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+
+/**
+ * Base class for Apache ACE cli commands that deal with ACE client.
+ * 
+ */
+public abstract class AbstractClientCommand extends AbstractCommand {
+
+    private AceClientWorkspace m_workspace;
+
+    public final void doCommand(String command) throws Exception {
+
+        String repositoryOption = getConfiguration().get("repository");
+        if (repositoryOption.equals("source")) {
+            throw new IllegalArgumentException(command + " can not work on source repository");
+        }
+
+        FixedIndexedRepo repository = getTargetRepository();
+        if (!(repository instanceof AceObrRepository)) {
+            throw new IllegalArgumentException("Manipulating artifacts requires an AceObrRepository target");
+        }
+        String location = repository.getLocation();
+        String endpoint = location.substring(0, location.lastIndexOf("/obr")) + "/client/work";
+
+        AceClient client = new AceClient(endpoint);
+        AceClientWorkspace workspace = client.createNewWorkspace();
+        m_workspace = workspace;
+
+        try {
+            doClientCommand(command, (AceObrRepository) repository, workspace);
+        }
+        finally {
+            workspace.remove();
+        }
+    }
+
+    public abstract void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception;
+
+    @SuppressWarnings("unchecked")
+    protected <T extends AbstractResource> T[] getFilteredResources(Class<T> resourceClass) throws Exception {
+        T[] resources = m_workspace.getResources(resourceClass);
+        String filter = getFilter();
+        if (filter == null) {
+            return resources;
+        }
+        List<AbstractResource> filtered = new ArrayList<AbstractResource>();
+        Filter f = FrameworkUtil.createFilter(filter);
+        for (AbstractResource resource : resources) {
+            if (f.match(toDictionary(resource))) {
+                filtered.add(resource);
+            }
+        }
+        return filtered.toArray((T[]) Array.newInstance(resourceClass, filtered.size()));
+    }
+
+    protected Dictionary<String, String> toDictionary(AbstractResource resource) {
+
+        Dictionary<String, String> dictionary = new Hashtable<String, String>();
+
+        // support ace specific filters
+        Map<String, String> attributes = resource.getAttributes();
+        for (Entry<String, String> entry : attributes.entrySet()) {
+            dictionary.put(entry.getKey(), entry.getValue());
+        }
+        Map<String, String> tags = resource.getTags();
+        for (Entry<String, String> entry : tags.entrySet()) {
+            dictionary.put(entry.getKey(), entry.getValue());
+        }
+
+        return dictionary;
+    }
+
+    protected Artifact findArtifact(Artifact[] artifacts, String bsn, String version) {
+        for (Artifact artifact : artifacts) {
+            if (artifact.getBundleSymbolicName().equals(bsn) && artifact.getBundleVersion().equals(version)) {
+                return artifact;
+            }
+        }
+        return null;
+    }
+    
+    protected void assignResourceAttrs(AbstractBuilder<?, ?> builder, String assignAttrs) throws Exception {
+        if (assignAttrs != null) {
+            String[] attrs = assignAttrs.split(",");
+            for (String arg : attrs) {
+                String[] keyVal = arg.trim().split("=");
+                if (keyVal.length != 2) {
+                    throw new IllegalArgumentException("Illegal assign-args specified...");
+                }
+                builder.setAttribute(keyVal[0].trim(), keyVal[1].trim());
+            }
+        }
+    }
+
+    protected void assignResourceTags(AbstractBuilder<?, ?> builder, String assignTags) throws Exception {
+        if (assignTags != null) {
+            String[] tags = assignTags.split(",");
+            for (String tag : tags) {
+                String[] keyVal = tag.trim().split("=");
+                if (keyVal.length != 2) {
+                    throw new IllegalArgumentException("Illegal assign-tags specified...");
+                }
+                builder.setTag(keyVal[0].trim(), keyVal[1].trim());
+            }
+        }
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractCommand.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractCommand.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractCommand.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/AbstractCommand.java Wed May 29 10:22:01 2013
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.Version;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.service.repository.Repository;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+import aQute.bnd.osgi.resource.CapReqBuilder;
+
+/**
+ * Base class for Apache ACE cli commands.
+ * 
+ */
+public abstract class AbstractCommand {
+
+    private Map<String, String> m_configuration;
+    private Map<String, FixedIndexedRepo> m_repositories;
+
+    private boolean m_verbose = false;
+
+    public final void execute(String command, Map<String, String> configuration, Map<String, FixedIndexedRepo> repositories, boolean verbose) throws Exception {
+        m_configuration = configuration;
+        m_repositories = repositories;
+        m_verbose = verbose;
+        doCommand(command);
+    }
+
+    protected abstract void doCommand(String command) throws Exception;
+
+    public abstract String getName();
+
+    public abstract String getDescription();
+
+    protected Map<String, String> getConfiguration() {
+        return m_configuration;
+    }
+
+    protected void printVerbose(String message) {
+        if (m_verbose)
+            System.out.println(message);
+    }
+
+    protected FixedIndexedRepo getSourceRepository() {
+        return m_repositories.get("source");
+    }
+
+    protected FixedIndexedRepo getTargetRepository() {
+        return m_repositories.get("target");
+    }
+
+    protected List<Resource> findResources(Repository repository, String bsn, String version, String type) {
+        Requirement requirement = new CapReqBuilder("osgi.identity")
+            .addDirective("filter", String.format("(&(osgi.identity=%s)(version=%s)(type=*))", bsn, version, type))
+            .buildSyntheticRequirement();
+        return findResources(repository, requirement);
+    }
+
+    protected List<Resource> findResources(Repository repository, Requirement requirement) {
+        Map<Requirement, Collection<Capability>> sourceResources = repository.findProviders(Collections.singleton(requirement));
+        if (sourceResources.isEmpty() || sourceResources.get(requirement).isEmpty()) {
+            return Collections.emptyList();
+        }
+        List<Resource> resources = new ArrayList<Resource>();
+        Iterator<Capability> capabilities = sourceResources.get(requirement).iterator();
+        while (capabilities.hasNext()) {
+            Capability capability = capabilities.next();
+            resources.add(capability.getResource());
+        }
+        return resources;
+    }
+
+    protected String getIdentity(Resource resource) {
+        return (String) resource.getCapabilities("osgi.identity").get(0).getAttributes().get("osgi.identity");
+
+    }
+
+    protected String getVersion(Resource resource) {
+        return ((Version) resource.getCapabilities("osgi.identity").get(0).getAttributes().get("version")).toString();
+
+    }
+
+    protected String getType(Resource resource) {
+        return (String) resource.getCapabilities("osgi.identity").get(0).getAttributes().get("type");
+    }
+
+    protected String getUrl(Resource resource) {
+        return ((URI) resource.getCapabilities("osgi.content").get(0).getAttributes().get("url")).toString();
+    }
+
+    protected String getMimetype(Resource resource) {
+        return (String) resource.getCapabilities("osgi.content").get(0).getAttributes().get("mime");
+    }
+
+    protected String toString(Resource resource) {
+        return getIdentity(resource) + "/" + getVersion(resource);
+    }
+
+    protected String getFilterNamespace() {
+        String namespace = "osgi.identity";
+        String argument = getConfiguration().get("filter");
+        if (argument != null) {
+            String[] args = argument.split(":");
+            if (args.length > 1) {
+                namespace = args[0];
+            }
+        }
+        return namespace;
+    }
+
+    protected String getFilter() {
+        String filter = null;
+        String argument = getConfiguration().get("filter");
+        if (argument != null) {
+            String[] args = argument.split(":");
+            if (args.length > 1) {
+                filter = args[1];
+            }
+            else {
+                filter = argument;
+            }
+        }
+        return filter;
+    }
+
+    protected Requirement getFilterRequirement() {
+        CapReqBuilder builder = new CapReqBuilder(getFilterNamespace());
+        String filter = getFilter();
+        if (filter != null) {
+            builder.addDirective("filter", getFilter());
+        }
+        return builder.buildSyntheticRequirement();
+    }
+
+    protected Requirement getIdentityRequirement(String bsn, String version) {
+        Requirement requirement = new CapReqBuilder("osgi.identity")
+            .addDirective("filter", String.format("(&(osgi.identity=%s)(version=%s))", bsn, version))
+            .buildSyntheticRequirement();
+        return requirement;
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CopyResources.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CopyResources.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CopyResources.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CopyResources.java Wed May 29 10:22:01 2013
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.List;
+
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+import aQute.bnd.service.RepositoryPlugin.PutOptions;
+import aQute.bnd.service.RepositoryPlugin.PutResult;
+import aQute.bnd.service.ResourceHandle;
+import aQute.bnd.service.Strategy;
+
+/**
+ * Command that copies resources from the source repository to the target repository.
+ * 
+ */
+public class CopyResources extends AbstractCommand {
+
+    @Override
+    public String getName() {
+        return "copy-resources";
+    }
+
+    @Override
+    public String getDescription() {
+        return "copy filtered resources from the source repository to the target repository";
+    }
+
+    @Override
+    public void doCommand(String command) throws Exception {
+
+        FixedIndexedRepo sourceRepo = getSourceRepository();
+        FixedIndexedRepo targetRepo = getTargetRepository();
+        if (!targetRepo.canWrite()) {
+            throw new IllegalArgumentException("The target repository is not writable");
+        }
+
+        Requirement requirement = getFilterRequirement();
+        List<Resource> sourceResources = findResources(sourceRepo, requirement);
+
+        int copyCount = 0;
+        int skipCount = 0;
+        printVerbose("Copying from source to target with directove " + getFilterNamespace() + ":" + getFilter());
+        for (Resource sourceResource : sourceResources) {
+
+            Requirement targetRequirement = getIdentityRequirement(getIdentity(sourceResource), getVersion(sourceResource));
+            List<Resource> targetResources = findResources(targetRepo, targetRequirement);
+            if (!targetResources.isEmpty()) {
+                String location = getUrl(targetResources.get(0));
+                System.out.println("Skipped " + toString(sourceResource) + " => " + location);
+                skipCount++;
+            }
+            else {
+
+                ResourceHandle handle = sourceRepo.getHandle(getIdentity(sourceResource), getVersion(sourceResource), Strategy.EXACT, null);
+                File file = handle.request();
+                InputStream input = new FileInputStream(file);
+                try {
+                    PutResult result = targetRepo.put(input, new PutOptions());
+                    System.out.println("Copied " + toString(sourceResource) + " => " + result.artifact.toString());
+                    copyCount++;
+                }
+                finally {
+                    input.close();
+                }
+            }
+        }
+        printVerbose("Copied " + copyCount + " resources (skipped " + skipCount + "existing)");
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifact.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifact.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifact.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifact.java Wed May 29 10:22:01 2013
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.ArtifactBuilder;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that create an artifact in the ACE client repository.
+ * 
+ */
+public class CreateArtifact extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "create-artifact";
+    }
+
+    @Override
+    public String getDescription() {
+        return "create artifact in the target repository";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        String name = getConfiguration().get("assign-name");
+        if (name == null || name.equals("")) {
+            throw new IllegalArgumentException("Creating an artifact requires at least a name");
+        }
+        String description = getConfiguration().get("assign-description");
+        if (description == null) {
+            description = "";
+        }
+
+        ArtifactBuilder builder = new ArtifactBuilder().setName(name).setDescription("");
+
+        String assignAttrs = getConfiguration().get("assign-attrs");
+        assignResourceAttrs(builder, assignAttrs);
+
+        String assignTags = getConfiguration().get("assign-tags");
+        assignResourceTags(builder, assignTags);
+
+        workspace.createResource(builder.build());
+
+        workspace.commit();
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifacts.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifacts.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifacts.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateArtifacts.java Wed May 29 10:22:01 2013
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import java.util.List;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.Artifact;
+import org.amdatu.ace.client.model.ArtifactBuilder;
+import org.apache.ace.cli.repository.AceObrRepository;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+import aQute.bnd.osgi.resource.CapReqBuilder;
+
+/**
+ * Command that creates artifacts in an ACE artifact repository based on the resources in an ACE OBR repository.
+ * 
+ */
+public class CreateArtifacts extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "create-artifacts";
+    }
+
+    @Override
+    public String getDescription() {
+        return "create artifacts in the target repository based on filtered resources (ACE repository only)";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        String namespace = getFilterNamespace();
+        String filter = getFilter();
+
+        Requirement requirement = new CapReqBuilder(namespace)
+            .addDirective("filter", filter)
+            .buildSyntheticRequirement();
+        List<Resource> resources = findResources(repository, requirement);
+
+        Artifact[] artifacts = workspace.getResources(Artifact.class);
+
+        int createCount = 0;
+        int skipCount = 0;
+        printVerbose("Creating artifacts in target repository with directive: " + namespace + ":" + filter + "\n--");
+        for (Resource resource : resources) {
+
+            String identity = getIdentity(resource);
+            String version = getVersion(resource);
+            String url = getUrl(resource);
+            String mimetype = getMimetype(resource);
+            if (mimetype == null) {
+                // OBR does not return mime
+                mimetype = Artifact.MIMETYPE_BUNDLE;
+            }
+
+            if (findArtifact(artifacts, identity, version) != null) {
+                System.out.println("Exists " + toString(resource) + " => skipping");
+                skipCount++;
+            }
+            else {
+                System.out.println("Created " + toString(resource));
+                workspace.createResource(
+                    new ArtifactBuilder()
+                        .setName(identity + version)
+                        .setDescription("")
+                        .setMimeType(mimetype)
+                        .setBundleName(identity)
+                        .setBundleSymbolicName(identity)
+                        .setBundleVersion(version)
+                        .setUrl(url)
+                        .build());
+                createCount++;
+            }
+        }
+
+        workspace.commit();
+        printVerbose("--\nCreated " + createCount + " artifacts. Skipped " + skipCount + " existing");
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateDistribution.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateDistribution.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateDistribution.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateDistribution.java Wed May 29 10:22:01 2013
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.DistributionBuilder;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that create distribution in the ACE client repository.
+ * 
+ */
+public class CreateDistribution extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "create-distribution";
+    }
+
+    @Override
+    public String getDescription() {
+        return "create distribution in the target repository";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        String name = getConfiguration().get("assign-name");
+        if (name == null || name.equals("")) {
+            throw new IllegalArgumentException("Creating an distribution requires at least a name");
+        }
+        String description = getConfiguration().get("assign-description");
+        if (description == null) {
+            description = "";
+        }
+
+        DistributionBuilder builder = new DistributionBuilder().setName(name).setDescription("");
+
+        String assignAttrs = getConfiguration().get("assign-attrs");
+        assignResourceAttrs(builder, assignAttrs);
+
+        String assignTags = getConfiguration().get("assign-tags");
+        assignResourceTags(builder, assignTags);
+
+        workspace.createResource(builder.build());
+
+        workspace.commit();
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateFeature.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateFeature.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateFeature.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateFeature.java Wed May 29 10:22:01 2013
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.FeatureBuilder;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that creates artifacts in an ACE artifact repository based on the resources in an ACE OBR repository.
+ * 
+ */
+public class CreateFeature extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "create-feature";
+    }
+
+    @Override
+    public String getDescription() {
+        return "create feature in the target repository based on filtered artifacts (ACE repository only)";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        String name = getConfiguration().get("assign-name");
+        if (name == null || name.equals("")) {
+            throw new IllegalArgumentException("Creating an argument requires at least a name");
+        }
+        String description = getConfiguration().get("assign-description");
+        if (description == null) {
+            description = "";
+        }
+
+        FeatureBuilder builder = new FeatureBuilder().setName(name).setDescription("");
+
+        String assignAttrs = getConfiguration().get("assign-attrs");
+        assignResourceAttrs(builder, assignAttrs);
+
+        String assignTags = getConfiguration().get("assign-tags");
+        assignResourceTags(builder, assignTags);
+
+        workspace.createResource(builder.build());
+
+        workspace.commit();
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateTarget.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateTarget.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateTarget.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/CreateTarget.java Wed May 29 10:22:01 2013
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.TargetBuilder;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that creates a target in the ACE client repository.
+ * 
+ */
+public class CreateTarget extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "create-target";
+    }
+
+    @Override
+    public String getDescription() {
+        return "create target in the target repository";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        String name = getConfiguration().get("assign-name");
+        if (name == null || name.equals("")) {
+            throw new IllegalArgumentException("Creating an target requires at least a name");
+        }
+
+        TargetBuilder builder = new TargetBuilder().setId(name);
+
+        String assignAttrs = getConfiguration().get("assign-attrs");
+        assignResourceAttrs(builder, assignAttrs);
+
+        String assignTags = getConfiguration().get("assign-tags");
+        assignResourceTags(builder, assignTags);
+
+        workspace.createResource(builder.build());
+
+        workspace.commit();
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteArtifacts.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteArtifacts.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteArtifacts.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteArtifacts.java Wed May 29 10:22:01 2013
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.Artifact;
+import org.apache.ace.cli.repository.AceObrRepository;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * Command that deletes artifacts from an ACE artifact repository.
+ * 
+ */
+public class DeleteArtifacts extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "delete-artifacts";
+    }
+
+    @Override
+    public String getDescription() {
+        return "delete artifacts from the target repository based on filter (ACE repository only)";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        String namespace = getFilterNamespace();
+        String filter = getFilter();
+        if (!namespace.equals("osgi.identity")) {
+            // don't knwo how to deal with this
+            throw new IllegalArgumentException("Delete artifacts filter must have osgi.identity namespace");
+        }
+
+        Filter f = FrameworkUtil.createFilter(filter);
+        Artifact[] artifacts = workspace.getResources(Artifact.class);
+
+        int deleteCount = 0;
+        printVerbose("Deleting artifacts in target repository with directive: " + namespace + ":" + filter + "\n--");
+        for (Artifact artifact : artifacts) {
+            if (f.match(toDictionary(artifact))) {
+                workspace.deleteResource(artifact);
+                deleteCount++;
+                System.out.println("Deleted : " + artifact.getBundleSymbolicName() + "/" + artifact.getBundleVersion());
+            }
+        }
+        workspace.commit();
+        printVerbose("--\nDeleted " + deleteCount + " artifact(s)");
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteResources.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteResources.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteResources.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/DeleteResources.java Wed May 29 10:22:01 2013
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.ace.cli.repository.AceObrRepository;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+
+/**
+ * Command that deletes resources from an ACE OBR repository.
+ * 
+ */
+public class DeleteResources extends AbstractCommand {
+
+    @Override
+    public String getName() {
+        return "delete-resources";
+    }
+
+    @Override
+    public String getDescription() {
+        return "delete filtered resources from the repository (ACE repository only)";
+    }
+
+    @Override
+    public void doCommand(String command) throws Exception {
+
+        String repositoryOption = getConfiguration().get("repository");
+        if (repositoryOption.equals("source")) {
+            throw new IllegalArgumentException("delete-resources can not work on source repository");
+        }
+
+        FixedIndexedRepo repository = getTargetRepository();
+        if (!(repository instanceof AceObrRepository)) {
+            throw new IllegalArgumentException("Deleting resources requires an AceObrRepository target");
+        }
+
+        Requirement requirement = getFilterRequirement();
+        List<Resource> resources = findResources(repository, requirement);
+
+        printVerbose("Deleting target repository resources with directive: " + getFilterNamespace() + ":" + getFilter() + "\n--");
+        for (Resource resource : resources) {
+            System.out.println("Deleting " + getIdentity(resource) + "/" + getVersion(resource) + "/" + getType(resource));
+            deleteResource(resource);
+        }
+        printVerbose("--\nFound " + resources.size() + " resource(s)");
+    }
+
+    private boolean deleteResource(Resource resource) throws Exception {
+        HttpURLConnection connection = null;
+        try {
+            URL endpointUrl = new URL(getUrl(resource));
+            connection = (HttpURLConnection) endpointUrl.openConnection();
+            connection.setDoInput(true);
+            connection.setDoOutput(false);
+            connection.setInstanceFollowRedirects(false);
+            connection.setRequestMethod("DELETE");
+            connection.connect();
+            return connection.getResponseCode() == 200;
+        }
+        finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListArtifacts.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListArtifacts.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListArtifacts.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListArtifacts.java Wed May 29 10:22:01 2013
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.Artifact;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that lists the artifacts in an ACE respository.
+ * 
+ */
+public class ListArtifacts extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "list-artifacts";
+    }
+
+    @Override
+    public String getDescription() {
+        return "list filtered artifacts from the target repository (ACE repository only)";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        Artifact[] artifacts = getFilteredResources(Artifact.class);
+        for (Artifact artifact : artifacts) {
+            System.out.println(artifact.getName() + ";attrs:" + artifact.getAttributes() + ";tags:" + artifact.getTags());
+        }
+        printVerbose("--\nFound " + artifacts.length + " artifact(s)");
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListDistributions.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListDistributions.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListDistributions.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListDistributions.java Wed May 29 10:22:01 2013
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.Distribution;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that lists features in an ACE artifact repository based on the resources in an ACE OBR repository.
+ * 
+ */
+public class ListDistributions extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "list-distributions";
+    }
+
+    @Override
+    public String getDescription() {
+        return "list distibutions in the client repository";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        Distribution[] distributions = getFilteredResources(Distribution.class);
+        for (Distribution feature : distributions) {
+            System.out.println(feature.getName() + ";attrs:" + feature.getAttributes() + ";tags:" + feature.getTags());
+        }
+        printVerbose("--\nFound " + distributions.length + " distribution(s)");
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListFeatures.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListFeatures.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListFeatures.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListFeatures.java Wed May 29 10:22:01 2013
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.Feature;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that lists features in an ACE artifact repository based on the resources in an ACE OBR repository.
+ * 
+ */
+public class ListFeatures extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "list-features";
+    }
+
+    @Override
+    public String getDescription() {
+        return "create feature in the target repository based on filtered artifacts (ACE repository only)";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        Feature[] features = getFilteredResources(Feature.class);
+        for (Feature feature : features) {
+            System.out.println(feature.getName() + ";attrs:" + feature.getAttributes() + ";tags:" + feature.getTags());
+        }
+        printVerbose("--\nFound " + features.length + " features(s)");
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListResources.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListResources.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListResources.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListResources.java Wed May 29 10:22:01 2013
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import java.util.List;
+
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+
+/**
+ * Command that lists the resources in a repository.
+ * 
+ */
+public class ListResources extends AbstractCommand {
+
+    @Override
+    public String getName() {
+        return "list-resources";
+    }
+
+    @Override
+    public String getDescription() {
+        return "list filtered resources from a repository";
+    }
+
+    @Override
+    public void doCommand(String command) throws Exception {
+
+        String repositoryOption = getConfiguration().get("repository");
+        FixedIndexedRepo repository = repositoryOption.equals("source") ? getSourceRepository() : getTargetRepository();
+
+        Requirement requirement = getFilterRequirement();
+        List<Resource> resources = findResources(repository, requirement);
+
+        printVerbose("Listing " + repositoryOption + " repository with directive: " + getFilterNamespace() + ":" + getFilter() + "\n--");
+        for (Resource resource : resources) {
+            System.out.println(getIdentity(resource) + "/" + getVersion(resource) + "/" + getType(resource));
+        }
+        printVerbose("--\nFound " + resources.size() + " resource(s)");
+    }
+
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListTargets.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListTargets.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListTargets.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/command/ListTargets.java Wed May 29 10:22:01 2013
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.command;
+
+import org.amdatu.ace.client.AceClientWorkspace;
+import org.amdatu.ace.client.model.Target;
+import org.apache.ace.cli.repository.AceObrRepository;
+
+/**
+ * Command that lists targets in an ACE client repository.
+ * 
+ */
+public class ListTargets extends AbstractClientCommand {
+
+    @Override
+    public String getName() {
+        return "list-targets";
+    }
+
+    @Override
+    public String getDescription() {
+        return "list targets in the client repository";
+    }
+
+    @Override
+    public void doClientCommand(String command, AceObrRepository repository, AceClientWorkspace workspace) throws Exception {
+
+        Target[] targets = getFilteredResources(Target.class);
+        for (Target target : targets) {
+            System.out.println(target.getId() + ";attrs:" + target.getAttributes() + ";tags:" + target.getTags());
+        }
+        printVerbose("--\nFound " + targets.length + " target(s)");
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java Wed May 29 10:22:01 2013
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ace.cli.repository;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Map;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+
+/**
+ * BND repository implementation that supports write capabilities to an Apache ACE OBR.
+ * 
+ */
+public class AceObrRepository extends FixedIndexedRepo {
+
+    private URL m_endpoint;
+    private boolean m_verbose;
+
+    @Override
+    public synchronized void setProperties(Map<String, String> map) {
+        super.setProperties(map);
+
+        String location = getLocation();
+        try {
+            m_endpoint = new URL(location.substring(0, location.lastIndexOf("/") + 1));
+        }
+        catch (MalformedURLException e) {
+            throw new IllegalArgumentException("Failed to determin location endpoint", e);
+        }
+        m_verbose = map.get("verbose") == null ? false : Boolean.parseBoolean(map.get("verbose"));
+    }
+
+    @Override
+    public boolean canWrite() {
+        return true;
+    }
+
+    @Override
+    public synchronized PutResult put(InputStream stream, PutOptions options) throws Exception {
+
+        if (options == null)
+            options = DEFAULTOPTIONS;
+
+        if (options.type == null)
+            options.type = PutOptions.BUNDLE;
+
+        if (stream == null)
+            throw new IllegalArgumentException("No stream and/or options specified");
+
+        PutResult result = new PutResult();
+        result.artifact = upload(m_endpoint, stream, "", options.type);
+
+        reset();
+        return result;
+    }
+
+    private URI upload(URL aceOBR, InputStream stream, String filename, String mimetype) throws Exception {
+
+        OutputStream output = null;
+        String location = null;
+        try {
+
+            URL url = new URL(aceOBR.toExternalForm() + "?filename=" + filename);
+            URLConnection connection = url.openConnection();
+            connection.setDoOutput(true);
+            connection.setDoInput(true);
+            connection.setUseCaches(false);
+
+            if (mimetype != null) {
+                connection.setRequestProperty("Content-Type", mimetype);
+            }
+
+            if (connection instanceof HttpURLConnection) {
+                ((HttpURLConnection) connection).setChunkedStreamingMode(8192);
+            }
+
+            int size = 0;
+            output = connection.getOutputStream();
+            byte[] buffer = new byte[4 * 1024];
+            for (int count = stream.read(buffer); count != -1; count = stream.read(buffer)) {
+                output.write(buffer, 0, count);
+                size += count;
+                if (m_verbose)
+                    System.err.println("Uploaded bytes... " + size);
+            }
+            output.close();
+
+            if (connection instanceof HttpURLConnection) {
+                int responseCode = ((HttpURLConnection) connection).getResponseCode();
+                String responseMessage = ((HttpURLConnection) connection).getResponseMessage();
+                switch (responseCode) {
+                    case HttpURLConnection.HTTP_CREATED:
+                        location = connection.getHeaderField("Location");
+                        break;
+                    case HttpURLConnection.HTTP_CONFLICT:
+                        throw new IOException("Resource already exists: " + responseMessage);
+                    case HttpURLConnection.HTTP_INTERNAL_ERROR:
+                        throw new IOException("Internal server error: " + responseMessage);
+                    default:
+                        throw new IOException("Unexpected server response: " + responseMessage);
+                }
+            }
+        }
+        catch (IOException e) {
+            throw new IOException("Error importing resource: " + e.getMessage());
+        }
+        finally {
+            if (output != null) {
+                try {
+                    output.close();
+                }
+                catch (Exception ex) {
+                }
+            }
+        }
+        return new URI(location);
+    }
+}

Added: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/packageinfo
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/packageinfo?rev=1487431&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/packageinfo (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/packageinfo Wed May 29 10:22:01 2013
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file

Added: ace/sandbox/bramk/org.apache.ace.cli/test/.gitignore
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/test/.gitignore?rev=1487431&view=auto
==============================================================================
    (empty)